@sprig-technologies/sprig-browser 2.31.0 → 2.31.2

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/dist/replay.js CHANGED
@@ -1 +1 @@
1
- var Oe=Object.defineProperty,je=(e,t,n)=>t in e?Oe(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,X=(e,t,n)=>(je(e,typeof t!="symbol"?t+"":t,n),n);import{i,s as Y,a as m,v as P,c as He,e as Z,P as ee,r as te,w as ne,b as Fe,d as x,f as R,S as L,g as Ge}from"./metricsReporter-DLAgtaq2.js";var $=(e=>(e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e))($||{});class We{constructor(t){X(this,"awaitingResolvers",[]),X(this,"activeCount",0),this.capacity=t}async acquire(){if(this.activeCount<this.capacity){this.activeCount++;return}return new Promise(t=>{this.awaitingResolvers.push(t)})}release(){const t=this.awaitingResolvers.shift();t&&this.activeCount<=this.capacity?t():this.activeCount--}async execute(t){try{return await this.acquire(),await t()}finally{this.release()}}setLimit(t){this.capacity=t}}const ae=new We(2),Ke=e=>ae.setLimit(e),Ve=async e=>ae.execute(async()=>{var t;i(`Beginning upload of chunk ${e.chunkIndex} for survey: ${e.surveyId}`);const n=await Y(e.uploadUrl,{body:e.data,method:"PUT"});i(`Completed upload of chunk ${e.chunkIndex} for survey: ${e.surveyId}`);const a=(t=n.headers)==null?void 0:t.get("ETag");if(!a)throw new Error(`Upload response did not include etag for upload ${e.uploadId}, part ${e.chunkIndex}`);return a}),re=async({apiUrl:e,surveyId:t,uploadId:n,etags:a,headers:r,responseGroupUuid:o,replayDuration:s,eventDigest:d},l=!1)=>{var u;if(!l&&!n&&!a){i(`Cannot mark upload complete: isMobile: ${l} / uploadId: ${n} / etags: ${a}`);return}i(`Marking upload complete for survey: ${t}`);const c=await Y(`${e}/sdk/1/completeSessionReplay`,{method:"POST",body:JSON.stringify({etags:a,uploadId:n,responseGroupUuid:o,surveyId:t,replayDuration:s,eventDigest:d,userAgent:(u=window?.navigator)==null?void 0:u.userAgent}),headers:r,shouldRetryRequest:!0});return i(`Done marking upload complete for survey: ${t}`),c},M=(e,t)=>t.some(n=>e instanceof n);let oe,se;function ze(){return oe||(oe=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function qe(){return se||(se=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}const O=new WeakMap,j=new WeakMap,B=new WeakMap;function Je(e){const t=new Promise((n,a)=>{const r=()=>{n(b(e.result))},o=()=>{a(e.error)};e.onsuccess=r,e.onerror=o});return B.set(t,e),t}function Qe(e){if(O.has(e))return;const t=new Promise((n,a)=>{const r=()=>{n()},o=()=>{a(e.error||new DOMException("AbortError","AbortError"))};e.oncomplete=r,e.onerror=o,e.onabort=o});O.set(e,t)}let H={get(e,t,n){if(e instanceof IDBTransaction){if(t==="done")return O.get(e);if(t==="store")return n.objectStoreNames[1]?void 0:n.objectStore(n.objectStoreNames[0])}return b(e[t])},set(e,t,n){return e[t]=n,!0},has(e,t){return e instanceof IDBTransaction&&(t==="done"||t==="store")?!0:t in e}};function ie(e){H=e(H)}function Xe(e){return qe().includes(e)?function(...t){return e.apply(F(this),t),b(this.request)}:function(...t){return b(e.apply(F(this),t))}}function Ye(e){return typeof e=="function"?Xe(e):(e instanceof IDBTransaction&&Qe(e),M(e,ze())?new Proxy(e,H):e)}function b(e){if(e instanceof IDBRequest)return Je(e);if(j.has(e))return j.get(e);const t=Ye(e);return t!==e&&(j.set(e,t),B.set(t,e)),t}const F=e=>B.get(e);function Ze(e,t,{blocked:n,upgrade:a,blocking:r,terminated:o}={}){const s=indexedDB.open(e,t),d=b(s);return a&&(s.onupgradeneeded=l=>{a(b(s.result),l.oldVersion,l.newVersion,b(s.transaction),l)}),n&&(s.onblocked=l=>n(l.oldVersion,l.newVersion,l)),d.then(l=>{o&&(l.onclose=()=>o()),r&&(l.onversionchange=u=>r(u.oldVersion,u.newVersion,u))}).catch(()=>{}),d}function le(e,{blocked:t}={}){const n=indexedDB.deleteDatabase(e);return t&&(n.onblocked=a=>t(a.oldVersion,a)),b(n).then(()=>{})}const et=["get","getKey","getAll","getAllKeys","count"],tt=["put","add","delete","clear"],G=new Map;function de(e,t){if(!(e instanceof IDBDatabase&&!(t in e)&&typeof t=="string"))return;if(G.get(t))return G.get(t);const n=t.replace(/FromIndex$/,""),a=t!==n,r=tt.includes(n);if(!(n in(a?IDBIndex:IDBObjectStore).prototype)||!(r||et.includes(n)))return;const o=async function(s,...d){const l=this.transaction(s,r?"readwrite":"readonly");let u=l.store;return a&&(u=u.index(d.shift())),(await Promise.all([u[n](...d),r&&l.done]))[0]};return G.set(t,o),o}ie(e=>({...e,get:(t,n,a)=>de(t,n)||e.get(t,n,a),has:(t,n)=>!!de(t,n)||e.has(t,n)}));const nt=["continue","continuePrimaryKey","advance"],ue={},W=new WeakMap,ce=new WeakMap,at={get(e,t){if(!nt.includes(t))return e[t];let n=ue[t];return n||(n=ue[t]=function(...a){W.set(this,ce.get(this)[t](...a))}),n}};async function*rt(...e){let t=this;if(t instanceof IDBCursor||(t=await t.openCursor(...e)),!t)return;t=t;const n=new Proxy(t,at);for(ce.set(n,t),B.set(n,F(t));t;)yield n,t=await(W.get(n)||t.continue()),W.delete(n)}function pe(e,t){return t===Symbol.asyncIterator&&M(e,[IDBIndex,IDBObjectStore,IDBCursor])||t==="iterate"&&M(e,[IDBIndex,IDBObjectStore])}ie(e=>({...e,get(t,n,a){return pe(t,n)?rt:e.get(t,n,a)},has(t,n){return pe(t,n)||e.has(t,n)}}));const ot=e=>{if(e instanceof Attr)return null;let t=1;for(let n=e.previousSibling;n;n=n.previousSibling)n.nodeName===e.nodeName&&++t;return t},ge=e=>{if(e===null)return"";const t=[];if(e instanceof Document)return"/";for(let n=e;n&&!(n instanceof Document)&&n!==null;n=n instanceof Attr?n.ownerElement:n.parentElement){const a=t[t.length]={name:void 0,position:null};switch(n.nodeType){case Node.TEXT_NODE:a.name="text()";break;case Node.ATTRIBUTE_NODE:a.name="@"+n.nodeName;break;case Node.PROCESSING_INSTRUCTION_NODE:a.name="processing-instruction()";break;case Node.COMMENT_NODE:a.name="comment()";break;case Node.ELEMENT_NODE:a.name=n.nodeName;break}a.position=ot(n)}return"/"+t.reverse().map(n=>n.position!==null?`/${n.name}[${n.position}]`:`/${n.name}`).join("")},D={capture:!0,passive:!0},st=["a","button","input","option","li","link"],it=["Escape","Enter","Backspace","F5","Tab"];let T=!1;const lt=["label","type","role","title","placeholder","errormessage","valuetext","href"],me="aria-",dt=e=>{if(!e.tagName)return"No tagName";const t=e.getAttribute("type");return t?`${t} ${e.tagName.toLowerCase()}`:e.tagName.toLowerCase()},ye=e=>{var t;if(((t=e.tagName)==null?void 0:t.toLowerCase())==="html")return{element:"html"};const n=e.textContent,a=n?{text:n}:{};a.element=dt(e);for(const r of e.attributes){let o=r.name;const s=r.value;o.startsWith(me)&&(o=o.substring(me.length)),lt.includes(o)&&(a[o]=s)}return a},ut=e=>{var t;if(!e)return{};const n={...ye(e)},a=e.parentElement;if(a&&st.includes((t=a.tagName)==null?void 0:t.toLowerCase())){const r=ye(a);Object.assign(n,r)}return n},we=(e,t)=>{var n;kt({x:t.x,y:t.y,type:e,elementAttributes:ut(t.target),windowHeight:window.innerHeight,windowWidth:window.innerWidth,...t.target instanceof HTMLElement?{rect:(n=t.target)==null?void 0:n.getBoundingClientRect(),xPath:ge(t.target)}:{}})},ct=e=>t=>we(e,t),fe=e=>{it.includes(e.key)&&$t({key:e.key})},pt=()=>{window.performance.getEntriesByType("navigation").map(e=>e.type).includes("reload")&&xt({url:window.location.href,currentPageTitle:document.title})},gt=()=>{window.performance.getEntriesByType("navigation").map(e=>e.type).includes("back_forward")&&Rt({curUrl:window.location.href,fromUrl:document.referrer,currentPageTitle:document.title})},mt=(e,t)=>{let n;return a=>{clearTimeout(n),n=window.setTimeout(()=>e(a),t)}},yt=e=>{if(!(e.target instanceof HTMLElement||e.target instanceof Document))return;let t=e.target;"scrollTop"in t||(t=t.documentElement),Bt({xPath:ge(t),x:t.scrollLeft,y:t.scrollTop,elementAttributes:{targetScrollWidth:t.scrollWidth,targetClientWidth:t.clientWidth,targetScrollHeight:t.scrollHeight,targetClientHeight:t.clientHeight}})},he=mt(yt,750),ve=ct("left_click"),Ie=e=>{e.button===2&&we("right_click",e)},wt=()=>{T||(window.addEventListener("click",ve,D),window.addEventListener("mousedown",Ie,D),window.addEventListener("keydown",fe,D),window.addEventListener("scroll",he,D),T=!0,pt(),gt())},ft=()=>{T&&(window.removeEventListener("click",ve,D),window.removeEventListener("mousedown",Ie,D),window.removeEventListener("keydown",fe,D),window.removeEventListener("scroll",he,D),T=!1)},ht=3e4;let C=0;const g={isRecording:!1,scrollEventUuids:{},stopRecording:()=>{}},vt=()=>{const e=m.getItem("sprig.sessionId");if(e)return i(`Found saved session id: ${e}`),m.removeItem("sprig.sessionId"),e;const t=P();return i(`Generating new uuid: ${t}`),t},w=vt(),It=async e=>{var t;if((t=window.navigator.storage)!=null&&t.estimate){const{quota:n=0,usage:a=0}=await window.navigator.storage.estimate();return(n-a)/1024**3>=e}return!0},Se=()=>{m.setItem("sprig.disableReplayRecording","disabled")},E=()=>!!m.getItem("sprig.disableReplayRecording");window.addEventListener("beforeunload",()=>{i(`Before page unload saving session id: ${w}`),m.setItem("sprig.sessionId",w)});const St=async()=>{const e=(await p.getPendingCaptures({isHeatmap:!0})).map(n=>({eventId:n.captureParams.eventId,uuid:n.uuid})),t=[];e.forEach(({eventId:n,uuid:a})=>{He(n)||t.push(a)}),t.length&&v(()=>p.markPendingHeatmapsReady(t),"Error marking pending heatmaps ready")},bt=e=>{if(e>1){C=0;return}const t=Date.now();if(!C){C=t;return}t-C>=ht&&(C=0,v(()=>p.markPendingHeatmapsReady(),"Error marking pending heatmaps ready"))},K=e=>e&&e.trim().substring(0,500).replace(/\s\s+/g," ").replace(/\r?\n|\r/g," ").substring(0,250),I=(e,t)=>{var n,a;if(g.isRecording)try{(a=(n=window.rrwebRecord)==null?void 0:n.addCustomEvent)==null||a.call(n,e,t)}catch(r){U("Error recording custom event",r)}},Dt=e=>{e.description&&(e.description=K(e.description)),I("Sprig_PageView",e)},kt=e=>{var t;(t=e?.elementAttributes)!=null&&t.text&&(e.elementAttributes.text=K(e.elementAttributes.text)),I("Sprig_Click",e)},Et=e=>{I("Sprig_TrackEvent",e)},Ct=e=>{I("Sprig_ShowSurvey",e)},Pt=e=>{I("Sprig_SubmitSurvey",e)},xt=e=>{I("Sprig_Refresh",e)},Rt=e=>{e.currentPageTitle&&(e.currentPageTitle=K(e.currentPageTitle)),I("Sprig_BackForward",e)},$t=e=>{I("Sprig_Keystroke",e)},Bt=async e=>{const{x:t,xPath:n,y:a}=e,r=g.scrollEventUuids[n];if(r)return v(async()=>{var o,s,d,l;const u=await p.openDB(),c=await u.get("events",r);if(c!=null&&c.event){const y=JSON.parse(c.event),h=t>((s=(o=y.data)==null?void 0:o.payload)==null?void 0:s.x),f=a>((l=(d=y.data)==null?void 0:d.payload)==null?void 0:l.y);if(!(h||f))return null;h&&(y.data.payload.x=t),f&&(y.data.payload.y=a),y.data.payload.elementAttributes=e.elementAttributes,c.event=JSON.stringify(y),await u.put("events",c)}else I("Sprig_Scroll",e)},"Error updating scroll event");I("Sprig_Scroll",e)},Tt=()=>g.isRecording,be=()=>{g.stopRecording&&(g.stopRecording(),g.stopRecording=void 0),g.isRecording=!1,["cleanupInterval","noopInterval","pendingCheckInterval"].forEach(e=>{g[e]&&(clearInterval(g[e]),g[e]=void 0)}),ft()},Ut=["did not allow mutations","called in an invalid security context"],At=e=>{if(!e)return!0;for(const t of Ut)if(e.toLowerCase().includes(t))return!1;return!0},Nt=(e,t,{reportError:n=!0,extraInfo:a})=>{E()||t instanceof Error&&(Se(),At(t?.message)&&(n&&window.UserLeap.reportError(e,t,a),p.clearAll()))},_t=async(e,t,{reportError:n}={reportError:!0})=>{var a;let r;try{if(n&&(a=window.navigator.storage)!=null&&a.estimate){const{quota:o=0,usage:s=0}=await window.navigator.storage.estimate();r={availableSpaceInMB:(o-s)/2**20,quota:o,usage:s}}}catch(o){window.UserLeap.reportError("Error getting storage estimate",o,{originalMessage:e,originalError:t})}Nt(e,t,{reportError:n,extraInfo:r})},U=(e,t,{reportError:n}={reportError:!0})=>(be(),Z(`${e} - ${JSON.stringify(t)}`),_t(e,t,{reportError:n})),v=async(e,t)=>{try{await e()}catch(n){U(t,n)}},Lt=()=>{g.isRecording&&v(()=>{var e,t;return(t=(e=window.rrwebRecord)==null?void 0:e.takeFullSnapshot)==null?void 0:t.call(e,!0)},"Error recording full snapshot")},Mt=async({surveyId:e,responseGroupUuid:t,eventDigest:n,headers:a})=>{if(!e||!t)return!1;const r=window.UserLeap._API_URL,o=await re({surveyId:e,responseGroupUuid:t,eventDigest:n,apiUrl:r,headers:a},!0);return!(o!=null&&o.error)},De=30,Ot=1;le("replayStorage").catch(console.error),le("sprig.replay").catch(console.error);class jt{openDB(){return Ze("sprigReplay",Ot,{upgrade:(t,n,a)=>{if(a===0&&m.setItem("sprig.pendingCount","0"),!t.objectStoreNames.contains("events")){const r=t.createObjectStore("events",{keyPath:"uuid"});r.createIndex("sessionId","sessionId"),r.createIndex("timestamp","timestamp"),r.createIndex("[sessionId+timestamp]",["sessionId","timestamp"])}if(!t.objectStoreNames.contains("chunkUploads")){const r=t.createObjectStore("chunkUploads",{keyPath:"uuid"});r.createIndex("sessionId","sessionId"),r.createIndex("timestamp","timestamp"),r.createIndex("[sessionId+status]",["sessionId","status"]),r.createIndex("[uploadId+status]",["uploadId","status"]),r.createIndex("[sessionId+status+uploadId]",["sessionId","status","uploadId"])}if(!t.objectStoreNames.contains("pendingCaptures")){const r=t.createObjectStore("pendingCaptures",{keyPath:"uuid"});r.createIndex("sessionId","sessionId"),r.createIndex("timestamp","timestamp"),r.createIndex("[sessionId+targetTimestamp]",["sessionId","targetTimestamp"])}}}).catch(t=>(Z(`Error opening replay storage: ${t.message}`),Se(),Promise.reject(t)))}constructor(){this.openDB()}async bulkAdd(t,n){const a=(await this.openDB()).transaction(t,"readwrite");return Promise.all([...n.map(r=>a.store.add(r)),a.done])}async clearAll(){const t=(await this.openDB()).transaction(["events","chunkUploads","pendingCaptures"],"readwrite");return Promise.allSettled([t.objectStore("events").clear(),t.objectStore("chunkUploads").clear(),t.objectStore("pendingCaptures").clear()])}async deleteBySessionId(t,n){const a=IDBKeyRange.only(n),r=(await this.openDB()).transaction(t,"readwrite");let o=await r.store.index("sessionId").openCursor(a);for(;o;)o.delete(),o=await o.continue();await r.done}async updatePartial(t,n,a){const r=(await this.openDB()).transaction(t,"readwrite"),o=await r.store.get(n);o&&await r.store.put({...o,...a}),await r.done}async deleteRowsBefore(t,n,a=()=>!0){const r=IDBKeyRange.upperBound(n,!0),o=(await this.openDB()).transaction(t,"readwrite");let s=await o.store.index("timestamp").openCursor(r);for(;s;)a(s.value)&&s.delete(),s=await s.continue();await o.done}async getEventsBetween(t,n=Date.now()){if(t>=n)return Promise.resolve([]);const a=IDBKeyRange.bound([w,t],[w,n],!1,!0);return(await this.openDB()).getAllFromIndex("events","[sessionId+timestamp]",a)}async updateEventsExpiredAt(t,n,a=De){const r=new Date,o=r.setMinutes(r.getMinutes()+(a??De)),s=(await this.openDB()).transaction("events","readwrite"),d=s.store.index("[sessionId+timestamp]"),l=IDBKeyRange.bound([w,t],[w,n],!1,!0);let u=await d.openCursor(l);for(;u;)u.update({...u.value,expiredAt:o}),u=await u.continue();await s.done}async deleteChunkUploads(t,n){const a=IDBKeyRange.only([n,t]),r=(await this.openDB()).transaction("chunkUploads","readwrite");let o=await r.store.index("[uploadId+status]").openCursor(a);for(;o;)o.delete(),o=await o.continue();await r.done}async getChunkUploadsByStatus({sessionId:t,status:n,uploadId:a}){const r=(await this.openDB()).transaction("chunkUploads","readonly"),o=a?r.store.index("[uploadId+status]"):r.store.index("[sessionId+status]"),s=a?IDBKeyRange.only([a,n]):IDBKeyRange.only([t,n]);return o.getAll(s)}async getPendingCaptures(t={}){return(await(await this.openDB()).getAllFromIndex("pendingCaptures","sessionId",w)).filter(n=>!t.beforePresent||n.targetTimestamp<Date.now()).filter(n=>!t.isHeatmap||(n.captureParams.isHeatmap??!1))}async markPendingCaptureToCanUpload(t){const n=(await this.openDB()).transaction("pendingCaptures","readwrite");let a=await n.store.index("sessionId").openCursor(w);for(;a;){const r=a.value;r.captureParams.responseGroupId===t&&a.update({...r,canUpload:!0}),a=await a.continue()}await n.done}async markPendingHeatmapsReady(t){if(parseInt(m.getItem("sprig.pendingCount")??"0")===0)return null;const n=Date.now(),a=(await this.openDB()).transaction("pendingCaptures","readwrite");let r=await a.store.index("sessionId").openCursor(w);for(;r;){const o=r.value;o.captureParams.isHeatmap&&(!t||t.includes(o.uuid))&&r.update({...o,targetTimestamp:n,captureParams:{...o.captureParams,triggerTimestamp:n,replayParams:{...o.captureParams.replayParams,replayDurationSeconds:Math.floor((n-o.timestamp)/1e3)}}}),r=await r.continue()}await a.done}}const p=new jt,Ht=async(e,t,n)=>new Promise((a,r)=>{const o=e.createElement("script");o.src=t,o.onload=a,o.onerror=r,n&&(o.nonce=n),e.head.appendChild(o)}),ke=async(e,t)=>{const n=performance.now();let a;try{a=await e()}finally{const r=performance.now()-n;let o=ee[t];o||(o=te(t)),o.report(r/1e3)}return a},Ee=(e,t)=>{const n=performance.now();try{e()}finally{const a=performance.now()-n;let r=ee[t];r||(r=te(t)),r.report(a/1e3)}};let Ce=1,V=5e3,A=6e4;const Pe=1e3,Ft=5,xe=30,N=xe+Ft;let Re=Date.now(),k,z=!!m.getItem("sprig.isCapturingHeatmap"),q=!1,J=[];const Gt=async({viewDocument:e,maxReplayDurationSeconds:t,replayNonce:n,maxInflightRequests:a=2,replaySettings:r,teardownAfter:o=!1})=>{k=m.getItem("sprig.pendingCount"),!g.isRecording&&(o&&m.setItem("sprig.teardownAfterCapture","true"),await v(async()=>{if(E()){i("Not initializing replay because recording is disabled");return}if(!t){i("Not initializing replay because config didn't specify maxReplayDurationSeconds");return}if(r!=null&&r.minAvailableGb&&(Ce=r.minAvailableGb),!await It(Ce)){ne("Minimum storage not available");return}if(i("Initializing replay"),r!=null&&r.minDuration&&(V=r.minDuration),r!=null&&r.batchDuration&&(A=r.batchDuration),Ke(a),Xt(),zt(t+N,30*60,t+N),qt(),!window.rrwebRecord){i("Loading recording script");const u=window.UserLeap.replayLibraryURL??"https://cdn.sprig.com/dependencies/record-2.0.0-alpha.6.min.js";await Ht(e,u,n),i("Recording script finished loading")}const s=window.rrwebRecord;if(!s){ne("Record script failed to set global function");return}let d=!0,l=0;g.stopRecording=s({checkoutEveryNms:xe*1e3,sampling:{input:"last",scroll:250,media:800},emit:(u,c)=>{if(E())return;if(Re=Date.now(),c&&u.type===$.Meta)l=performance.now();else if(c&&l&&u.type===$.FullSnapshot){const h=performance.now()-l;Fe("sdk_replay_snapshot_seconds",h/1e3)}const y=d||!!c&&u.type===$.Meta;d=!1,Wt({uuid:P(),event:JSON.stringify(u),isValidStart:y,timestamp:Date.now()})},...r}),g.isRecording=!!g.stopRecording,g.isRecording&&(g.noopInterval||(g.noopInterval=window.setInterval(()=>{Date.now()-Re>Pe&&I("Sprig_Noop",{})},Pe)),x.on("survey.complete",u=>{Pt({id:u,userAgent:window.navigator.userAgent})}),wt())},"Error initializing replay"))},Wt=e=>{var t,n,a,r;if((t=e.event)!=null&&t.includes("Sprig_Scroll")){const o=(r=(a=(n=JSON.parse(e.event))==null?void 0:n.data)==null?void 0:a.payload)==null?void 0:r.xPath;if(!o)return;g.scrollEventUuids[o]=e.uuid}J.push(e),q||Vt()},Kt=async e=>{const t=e.map(n=>({...n,sessionId:n.sessionId??w}));if(z&&bt(t.length),t.length!==0)return v(()=>p.bulkAdd("events",t),"Error storing replay events")},Vt=()=>{q=!0,setTimeout(async()=>{if(E())return;const e=J;J=[],q=!1,Ee(async()=>{await Kt(e)},"sdk_replay_add_event_batch_seconds")},500)},zt=(e,t,n)=>{g.cleanupInterval=window.setInterval(()=>{const a=Date.now();E()||(R(`Performing periodic replay data cleanup / Event Seconds ${e} / Chunk Seconds ${t} / Pending Capture Seconds ${n}`),ke(()=>v(async()=>{const r=(await Promise.allSettled([p.deleteRowsBefore("events",a-e*1e3,o=>o.expiredAt===void 0||o.expiredAt<a-e*1e3),p.deleteRowsBefore("chunkUploads",a-t*1e3),p.deleteRowsBefore("pendingCaptures",a-n*1e3,o=>!o.canUpload)])).find(o=>o.status==="rejected");if(r)throw new Error(r.reason)},"Error deleting table rows"),"sdk_replay_cleanup_seconds"),i("Cleanup complete"))},3e4)},qt=()=>{g.pendingCheckInterval=window.setInterval(async()=>{v(async()=>{const e=parseInt(k??"0");if(e===0)return;const t=await p.getPendingCaptures({beforePresent:!0}),n=await p.openDB();await Promise.all(t.map(async a=>(await n.delete("pendingCaptures",a.uuid),Ae(a.captureParams,a.canUpload)))),k=(e-t.length).toString(),m.setItem("sprig.pendingCount",k)},"Error initiating pending captures")},5e3)},Jt=async(e,t,n,a,r)=>{const o=Math.min(e+r,n),s=`from: ${new Date(e).toLocaleTimeString()} to ${new Date(o).toLocaleTimeString()}`;i(`Getting event batch ${s}`);const d=await ke(()=>p.getEventsBetween(e,o),"sdk_replay_get_events_between_seconds");if(!(d!=null&&d.length))return i(`No events found ${s}`),{validStartFound:a,events:[]};if(!a){i(`Searching for valid start in ${d.length} events ${s}`);let l=-1;if(d?.forEach((c,y)=>{if(!c.isValidStart)return;const h=c.timestamp<=t;(l<0||h)&&(l=y)}),l<0)return i(`No valid start found in ${d.length} events ${s}`),{validStartFound:a,events:[]};const u=d[l].timestamp;return i(`Found valid start at: ${new Date(u).toLocaleTimeString()} in events ${s}`),{validStartFound:!0,events:d?.slice(l)}}return{validStartFound:a,events:d}},Qt=(e,t,n)=>{const a=e.length,r=t*1024*1024,o=Math.ceil(a/n),s=Math.max(r,o);i(`Total file bytes: ${a} / target chunk size: ${s}`);const d=[];let l=0;for(;l<a;)d.push(e.slice(l,l+s)),l+=s;return d},$e=e=>Promise.all(e.map(async t=>{const n=await Ve(t);return await p.updatePartial("chunkUploads",t.uuid,{data:null,etag:n,status:"UploadComplete"}),t.uploadId})),Be=async e=>{i(`Marking upload complete if finished: ${e}`);const t=await p.getChunkUploadsByStatus({status:"UploadComplete",uploadId:e});if(!(t!=null&&t.length)){i(`No finished chunks found for upload: ${e}`);return}const n=t.reduce((o,s)=>(o.find(d=>d.chunkIndex===s.chunkIndex)||o.push(s),o),[]);n.sort((o,s)=>o.chunkIndex-s.chunkIndex);const a=n.map(o=>({ETag:o.etag,PartNumber:o.chunkIndex})).filter(o=>o.ETag!==null),r=n[0];await re({apiUrl:r.apiUrl,surveyId:r.surveyId,uploadId:e,responseGroupUuid:r.responseGroupId,etags:a,headers:r.completeUploadHeaders,replayDuration:r.replayDuration}),i(`Cleaning up chunks for ${e}`),await p.deleteChunkUploads("UploadComplete",e),i(`Done cleaning up chunks for ${e}`)},Xt=async()=>{v(async()=>{const e=await p.getChunkUploadsByStatus({sessionId:w,status:"ReadyForUpload"});if(!(e!=null&&e.length))return;const t=await $e(e);i(`Finished uploading unfinished chunks for ${t}`),t!=null&&t.length&&await Promise.all(t.map(n=>{if(n)return Be(n)}))},"Error uploading unfinished chunks")},Yt=async(e,t)=>{await $e(t),i(`Done uploading chunks for uploads: ${e.join(",")}`),await Promise.all(e.map(n=>Be(n)))},Zt=e=>{let t=0;e.forEach(r=>{t+=r.length});const n=new Uint8Array(t);let a=0;return e.forEach(r=>{n.set(r,a),a+=r.length}),n},Te=async(e,t,n)=>{const a=new TextEncoder;let r=null,o=null,s=null,d=!1,l=!1,[u,c]=[0,0];const y=e-N*1e3,h=[];let f=[];i(`Getting events between ${new Date(e).toLocaleTimeString()} and ${new Date(t).toLocaleTimeString()}`),i(`Using batch duration: ${A}ms`);for(let _=y;_<t;_+=A){if({validStartFound:l,events:f}=await Jt(_,e,t,l,A),!(f!=null&&f.length)){i("No events found");continue}u===0&&(u=f[0].timestamp),c=f[f.length-1].timestamp,i(`Last event time in batch: ${new Date(c).toLocaleTimeString()}`);const Le=`${d?",":"["}${f.map(Me=>Me.event).join(",")}`,Q=a.encode(Le);n&&o===null&&(R("Attempting compression"),s=new window.CompressionStream("gzip"),o=s.writable.getWriter()),Ee(()=>{n&&o?o.write(Q):h.push(Q)},"sdk_replay_compression_seconds"),d=!0}if(c-u<V)return i(`Replay duration is shorter than minimum of ${V}ms / Start:${u} / End:${c}`),null;const S=a.encode("]");return R("Writing final close brace"),o&&s?(o.write(S),o.close(),r=new Uint8Array(await new Response(s.readable).arrayBuffer())):(h.push(S),r=Zt(h)),i("Finished generating file data"),r},en=async(e,t)=>{const n=window.CompressionStream!==void 0;let a=null;const r=t??Date.now(),o=r-e;try{a=await Te(o,r,n)}catch(s){s instanceof Error&&window.UserLeap.reportError("Error compressing replay",s),n&&v(async()=>{await Te(o,r,!1)},"fileData fallback failed")}return a},Ue=async e=>{const{surveyId:t,responseGroupId:n,visitorId:a,apiUrl:r,completeUploadHeaders:o,replayParams:s,triggerTimestamp:d}=e,l=await en(s.replayDurationSeconds*1e3,d);if(l!=null&&l.length)i(`Found file data for survey: ${t}`);else{i(`File data is empty for survey: ${t}`);return}const u=Qt(l,s.minimumChunkSizeMb,s.signedUrls.length);i(`Got ${u.length} chunks for survey: ${t}`);const c=await Promise.all(u.map(async(y,h)=>{const f=P(),S={apiUrl:r,chunkIndex:h+1,completeUploadHeaders:o,etag:null,responseGroupId:n,status:"ReadyForUpload",surveyId:t,timestamp:d,totalChunks:u.length,data:y,uploadId:s.uploadId,uploadUrl:s.signedUrls[h].url,uuid:f,visitorId:a};return i(`Recording chunk upload: ${JSON.stringify({index:S.chunkIndex,surveyId:S.surveyId,uploadId:S.uploadId,size:y.length,id:f},null,2)}`),await(await p.openDB()).add("chunkUploads",{...S,sessionId:S.sessionId??w}),i(`Done creating chunk upload: ${f}`),S}));i(`All chunk records created. Beginning upload for survey: ${t}`),await Yt([s.uploadId],c)},Ae=async(e,t)=>{if(i(`Attempting replay capture: ${JSON.stringify({isStandalone:e.isStandalone,duration:e.replayParams.replayDurationSeconds,type:e.replayParams.replayDurationType,responseGroupId:e.responseGroupId,surveyId:e.surveyId,triggerTimestamp:e.triggerTimestamp,visitorId:e.visitorId},null,2)}`),E())return i(`Replay recording is disabled: ${e.surveyId}`);i(`Replay recording enabled: ${e.surveyId}`);const{isHeatmap:n,isStandalone:a,replayParams:r,triggerTimestamp:o,responseGroupId:s}=e,d=async()=>{setTimeout(()=>x.removeListener(L.QuestionAnswered,d),0),v(async()=>{r.replayDurationType==="before"?await Ue(e):await p.markPendingCaptureToCanUpload(s)},"Error in schedule/capture callback")};v(async()=>{if(r.replayDurationType==="after"||r.replayDurationType==="beforeAndAfter"){!a&&!n&&(i("Attaching QuestionAnswered listener for non-standalone replay"),x.on(L.QuestionAnswered,d)),i(`Scheduling capture for replay of type: ${r.replayDurationType}`),await _e(e);return}if(a||n||t)i(`Proceeding to capture replay for survey: ${e.surveyId} / standalone? ${a} / canUpload? ${t}`),await Ue(e),n&&tn();else{const l=N+r.replayDurationSeconds,u=o-l*1e3,c=o;i(`Setting expiry minutes to ${r.expirationTimeLimitMinutes} for events from ${new Date(u).toLocaleTimeString()} to ${new Date(c).toLocaleTimeString()}`),await p.updateEventsExpiredAt(u,c,r.expirationTimeLimitMinutes),i("Attaching QuestionAnswered listener"),x.on(L.QuestionAnswered,d)}},"Error in scheduling/capturing replay")},tn=async()=>{parseInt(k??"0")||(m.removeItem("sprig.isCapturingHeatmap"),z=!1),m.getItem("sprig.teardownAfterCapture")&&(be(),Ne(),m.removeItem("sprig.teardownAfterCapture"))},Ne=()=>{if(E()){R("Not clearing user data, replay is disabled");return}return Promise.allSettled([p.deleteBySessionId("events",w),p.deleteBySessionId("pendingCaptures",w)]).then(e=>{var t;const n=(t=e.find(a=>a.status==="rejected"))==null?void 0:t.reason;n&&U("Error clearing session event data",n)})},_e=async e=>{i(`Scheduling replay capture: ${JSON.stringify(e)}`);const{isHeatmap:t,surveyId:n}=e,a=await p.getPendingCaptures(),r=a?.filter(d=>d.captureParams.surveyId===n);if(r!=null&&r.length){i(`Pending capture exists for survey: ${n}`);return}t&&(Lt(),z=!0,m.setItem("sprig.isCapturingHeatmap","true"));const o={...e,replayParams:{...e.replayParams}};e.replayParams.replayDurationType==="beforeAndAfter"&&(o.replayParams.replayDurationSeconds*=2),o.replayParams.replayDurationType="before";const s=e.triggerTimestamp+e.replayParams.replayDurationSeconds*1e3;o.triggerTimestamp=s,k=(parseInt(k??"0")+1).toString(),m.setItem("sprig.pendingCount",k),await(await p.openDB()).add("pendingCaptures",{canUpload:!1,captureParams:o,sessionId:w,targetTimestamp:s,timestamp:Date.now(),uuid:P()})},nn=Object.freeze(Object.defineProperty({__proto__:null,RecordEvent:Et,RecordPageView:Dt,RecordSurveyShown:Ct,_completeSessionReplay:Mt,checkPendingHeatmapsUrl:St,clearUserReplayData:Ne,disableRecording:U,initializeReplay:Gt,isReplayRecording:Tt,scheduleCapture:_e,scheduleOrCaptureReplay:Ae},Symbol.toStringTag,{value:"Module"}));Ge(nn);
1
+ var Oe=Object.defineProperty,je=(e,t,n)=>t in e?Oe(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Y=(e,t,n)=>(je(e,typeof t!="symbol"?t+"":t,n),n);import{i,s as Z,a as m,v as P,c as He,e as ee,P as te,r as ne,w as ae,b as Fe,d as x,f as R,S as L,g as Ge}from"./metricsReporter-D-m62w_D.js";var $=(e=>(e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e))($||{});class We{constructor(t){Y(this,"awaitingResolvers",[]),Y(this,"activeCount",0),this.capacity=t}async acquire(){if(this.activeCount<this.capacity){this.activeCount++;return}return new Promise(t=>{this.awaitingResolvers.push(t)})}release(){const t=this.awaitingResolvers.shift();t&&this.activeCount<=this.capacity?t():this.activeCount--}async execute(t){try{return await this.acquire(),await t()}finally{this.release()}}setLimit(t){this.capacity=t}}const re=new We(2),Ke=e=>re.setLimit(e),Ve=async e=>re.execute(async()=>{var t;i(`Beginning upload of chunk ${e.chunkIndex} for survey: ${e.surveyId}`);const n=await Z(e.uploadUrl,{body:e.data,method:"PUT"});i(`Completed upload of chunk ${e.chunkIndex} for survey: ${e.surveyId}`);const a=(t=n.headers)==null?void 0:t.get("ETag");if(!a)throw new Error(`Upload response did not include etag for upload ${e.uploadId}, part ${e.chunkIndex}`);return a}),oe=async({apiUrl:e,surveyId:t,uploadId:n,etags:a,headers:r,responseGroupUuid:o,replayDuration:s,eventDigest:d},l=!1)=>{var u;if(!l&&!n&&!a){i(`Cannot mark upload complete: isMobile: ${l} / uploadId: ${n} / etags: ${a}`);return}i(`Marking upload complete for survey: ${t}`);const c=await Z(`${e}/sdk/1/completeSessionReplay`,{method:"POST",body:JSON.stringify({etags:a,uploadId:n,responseGroupUuid:o,surveyId:t,replayDuration:s,eventDigest:d,userAgent:(u=window?.navigator)==null?void 0:u.userAgent}),headers:r,shouldRetryRequest:!0});return i(`Done marking upload complete for survey: ${t}`),c},M=(e,t)=>t.some(n=>e instanceof n);let se,ie;function ze(){return se||(se=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function qe(){return ie||(ie=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}const O=new WeakMap,j=new WeakMap,B=new WeakMap;function Je(e){const t=new Promise((n,a)=>{const r=()=>{n(D(e.result))},o=()=>{a(e.error)};e.onsuccess=r,e.onerror=o});return B.set(t,e),t}function Qe(e){if(O.has(e))return;const t=new Promise((n,a)=>{const r=()=>{n()},o=()=>{a(e.error||new DOMException("AbortError","AbortError"))};e.oncomplete=r,e.onerror=o,e.onabort=o});O.set(e,t)}let H={get(e,t,n){if(e instanceof IDBTransaction){if(t==="done")return O.get(e);if(t==="store")return n.objectStoreNames[1]?void 0:n.objectStore(n.objectStoreNames[0])}return D(e[t])},set(e,t,n){return e[t]=n,!0},has(e,t){return e instanceof IDBTransaction&&(t==="done"||t==="store")?!0:t in e}};function le(e){H=e(H)}function Xe(e){return qe().includes(e)?function(...t){return e.apply(F(this),t),D(this.request)}:function(...t){return D(e.apply(F(this),t))}}function Ye(e){return typeof e=="function"?Xe(e):(e instanceof IDBTransaction&&Qe(e),M(e,ze())?new Proxy(e,H):e)}function D(e){if(e instanceof IDBRequest)return Je(e);if(j.has(e))return j.get(e);const t=Ye(e);return t!==e&&(j.set(e,t),B.set(t,e)),t}const F=e=>B.get(e);function Ze(e,t,{blocked:n,upgrade:a,blocking:r,terminated:o}={}){const s=indexedDB.open(e,t),d=D(s);return a&&(s.onupgradeneeded=l=>{a(D(s.result),l.oldVersion,l.newVersion,D(s.transaction),l)}),n&&(s.onblocked=l=>n(l.oldVersion,l.newVersion,l)),d.then(l=>{o&&(l.onclose=()=>o()),r&&(l.onversionchange=u=>r(u.oldVersion,u.newVersion,u))}).catch(()=>{}),d}function G(e,{blocked:t}={}){const n=indexedDB.deleteDatabase(e);return t&&(n.onblocked=a=>t(a.oldVersion,a)),D(n).then(()=>{})}const et=["get","getKey","getAll","getAllKeys","count"],tt=["put","add","delete","clear"],W=new Map;function de(e,t){if(!(e instanceof IDBDatabase&&!(t in e)&&typeof t=="string"))return;if(W.get(t))return W.get(t);const n=t.replace(/FromIndex$/,""),a=t!==n,r=tt.includes(n);if(!(n in(a?IDBIndex:IDBObjectStore).prototype)||!(r||et.includes(n)))return;const o=async function(s,...d){const l=this.transaction(s,r?"readwrite":"readonly");let u=l.store;return a&&(u=u.index(d.shift())),(await Promise.all([u[n](...d),r&&l.done]))[0]};return W.set(t,o),o}le(e=>({...e,get:(t,n,a)=>de(t,n)||e.get(t,n,a),has:(t,n)=>!!de(t,n)||e.has(t,n)}));const nt=["continue","continuePrimaryKey","advance"],ue={},K=new WeakMap,ce=new WeakMap,at={get(e,t){if(!nt.includes(t))return e[t];let n=ue[t];return n||(n=ue[t]=function(...a){K.set(this,ce.get(this)[t](...a))}),n}};async function*rt(...e){let t=this;if(t instanceof IDBCursor||(t=await t.openCursor(...e)),!t)return;t=t;const n=new Proxy(t,at);for(ce.set(n,t),B.set(n,F(t));t;)yield n,t=await(K.get(n)||t.continue()),K.delete(n)}function pe(e,t){return t===Symbol.asyncIterator&&M(e,[IDBIndex,IDBObjectStore,IDBCursor])||t==="iterate"&&M(e,[IDBIndex,IDBObjectStore])}le(e=>({...e,get(t,n,a){return pe(t,n)?rt:e.get(t,n,a)},has(t,n){return pe(t,n)||e.has(t,n)}}));const ot=e=>{if(e instanceof Attr)return null;let t=1;for(let n=e.previousSibling;n;n=n.previousSibling)n.nodeName===e.nodeName&&++t;return t},ge=e=>{if(e===null)return"";const t=[];if(e instanceof Document)return"/";for(let n=e;n&&!(n instanceof Document)&&n!==null;n=n instanceof Attr?n.ownerElement:n.parentElement){const a=t[t.length]={name:void 0,position:null};switch(n.nodeType){case Node.TEXT_NODE:a.name="text()";break;case Node.ATTRIBUTE_NODE:a.name="@"+n.nodeName;break;case Node.PROCESSING_INSTRUCTION_NODE:a.name="processing-instruction()";break;case Node.COMMENT_NODE:a.name="comment()";break;case Node.ELEMENT_NODE:a.name=n.nodeName;break}a.position=ot(n)}return"/"+t.reverse().map(n=>n.position!==null?`/${n.name}[${n.position}]`:`/${n.name}`).join("")},S={capture:!0,passive:!0},st=["a","button","input","option","li","link"],it=["Escape","Enter","Backspace","F5","Tab"];let T=!1;const lt=["label","type","role","title","placeholder","errormessage","valuetext","href"],me="aria-",dt=e=>{if(!e.tagName)return"No tagName";const t=e.getAttribute("type");return t?`${t} ${e.tagName.toLowerCase()}`:e.tagName.toLowerCase()},ye=e=>{var t;if(((t=e.tagName)==null?void 0:t.toLowerCase())==="html")return{element:"html"};const n=e.textContent,a=n?{text:n}:{};a.element=dt(e);for(const r of e.attributes){let o=r.name;const s=r.value;o.startsWith(me)&&(o=o.substring(me.length)),lt.includes(o)&&(a[o]=s)}return a},ut=e=>{var t;if(!e)return{};const n={...ye(e)},a=e.parentElement;if(a&&st.includes((t=a.tagName)==null?void 0:t.toLowerCase())){const r=ye(a);Object.assign(n,r)}return n},we=(e,t)=>{var n;kt({x:t.x,y:t.y,type:e,elementAttributes:ut(t.target),windowHeight:window.innerHeight,windowWidth:window.innerWidth,...t.target instanceof HTMLElement?{rect:(n=t.target)==null?void 0:n.getBoundingClientRect(),xPath:ge(t.target)}:{}})},ct=e=>t=>we(e,t),fe=e=>{it.includes(e.key)&&$t({key:e.key})},pt=()=>{window.performance.getEntriesByType("navigation").map(e=>e.type).includes("reload")&&xt({url:window.location.href,currentPageTitle:document.title})},gt=()=>{window.performance.getEntriesByType("navigation").map(e=>e.type).includes("back_forward")&&Rt({curUrl:window.location.href,fromUrl:document.referrer,currentPageTitle:document.title})},mt=(e,t)=>{let n;return a=>{clearTimeout(n),n=window.setTimeout(()=>e(a),t)}},yt=e=>{if(!(e.target instanceof HTMLElement||e.target instanceof Document))return;let t=e.target;"scrollTop"in t||(t=t.documentElement),Bt({xPath:ge(t),x:t.scrollLeft,y:t.scrollTop,elementAttributes:{targetScrollWidth:t.scrollWidth,targetClientWidth:t.clientWidth,targetScrollHeight:t.scrollHeight,targetClientHeight:t.clientHeight}})},he=mt(yt,750),ve=ct("left_click"),Ie=e=>{e.button===2&&we("right_click",e)},wt=()=>{T||(window.addEventListener("click",ve,S),window.addEventListener("mousedown",Ie,S),window.addEventListener("keydown",fe,S),window.addEventListener("scroll",he,S),T=!0,pt(),gt())},ft=()=>{T&&(window.removeEventListener("click",ve,S),window.removeEventListener("mousedown",Ie,S),window.removeEventListener("keydown",fe,S),window.removeEventListener("scroll",he,S),T=!1)},ht=3e4;let C=0;const g={isRecording:!1,scrollEventUuids:{},stopRecording:()=>{}},vt=()=>{const e=m.getItem("sprig.sessionId");if(e)return i(`Found saved session id: ${e}`),m.removeItem("sprig.sessionId"),e;const t=P();return i(`Generating new uuid: ${t}`),t},w=vt(),It=async e=>{var t;if((t=window.navigator.storage)!=null&&t.estimate){const{quota:n=0,usage:a=0}=await window.navigator.storage.estimate();return(n-a)/1024**3>=e}return!0},be=()=>{m.setItem("sprig.disableReplayRecording","disabled")},E=()=>!!m.getItem("sprig.disableReplayRecording");window.addEventListener("beforeunload",()=>{i(`Before page unload saving session id: ${w}`),m.setItem("sprig.sessionId",w)});const bt=async()=>{const e=(await p.getPendingCaptures({isHeatmap:!0})).map(n=>({eventId:n.captureParams.eventId,uuid:n.uuid})),t=[];e.forEach(({eventId:n,uuid:a})=>{He(n)||t.push(a)}),t.length&&v(()=>p.markPendingHeatmapsReady(t),"Error marking pending heatmaps ready")},Dt=e=>{if(e>1){C=0;return}const t=Date.now();if(!C){C=t;return}t-C>=ht&&(C=0,v(()=>p.markPendingHeatmapsReady(),"Error marking pending heatmaps ready"))},V=e=>e&&e.trim().substring(0,500).replace(/\s\s+/g," ").replace(/\r?\n|\r/g," ").substring(0,250),I=(e,t)=>{var n,a;if(g.isRecording)try{(a=(n=window.rrwebRecord)==null?void 0:n.addCustomEvent)==null||a.call(n,e,t)}catch(r){U("Error recording custom event",r)}},St=e=>{e.description&&(e.description=V(e.description)),I("Sprig_PageView",e)},kt=e=>{var t;(t=e?.elementAttributes)!=null&&t.text&&(e.elementAttributes.text=V(e.elementAttributes.text)),I("Sprig_Click",e)},Et=e=>{I("Sprig_TrackEvent",e)},Ct=e=>{I("Sprig_ShowSurvey",e)},Pt=e=>{I("Sprig_SubmitSurvey",e)},xt=e=>{I("Sprig_Refresh",e)},Rt=e=>{e.currentPageTitle&&(e.currentPageTitle=V(e.currentPageTitle)),I("Sprig_BackForward",e)},$t=e=>{I("Sprig_Keystroke",e)},Bt=async e=>{const{x:t,xPath:n,y:a}=e,r=g.scrollEventUuids[n];if(r)return v(async()=>{var o,s,d,l;const u=await p.openDB(),c=await u.get("events",r);if(c!=null&&c.event){const y=JSON.parse(c.event),h=t>((s=(o=y.data)==null?void 0:o.payload)==null?void 0:s.x),f=a>((l=(d=y.data)==null?void 0:d.payload)==null?void 0:l.y);if(!(h||f))return null;h&&(y.data.payload.x=t),f&&(y.data.payload.y=a),y.data.payload.elementAttributes=e.elementAttributes,c.event=JSON.stringify(y),await u.put("events",c)}else I("Sprig_Scroll",e)},"Error updating scroll event");I("Sprig_Scroll",e)},Tt=()=>g.isRecording,De=()=>{g.stopRecording&&(g.stopRecording(),g.stopRecording=void 0),g.isRecording=!1,["cleanupInterval","noopInterval","pendingCheckInterval"].forEach(e=>{g[e]&&(clearInterval(g[e]),g[e]=void 0)}),ft()},Ut=["did not allow mutations","called in an invalid security context"],At=e=>{if(!e)return!0;for(const t of Ut)if(e.toLowerCase().includes(t))return!1;return!0},Nt=(e,t,{reportError:n=!0,extraInfo:a})=>{E()||t instanceof Error&&(be(),At(t?.message)&&(n&&window.UserLeap.reportError(e,t,a),p.clearAll()))},_t=async(e,t,{reportError:n}={reportError:!0})=>{var a;let r;try{if(n&&(a=window.navigator.storage)!=null&&a.estimate){const{quota:o=0,usage:s=0}=await window.navigator.storage.estimate();r={availableSpaceInMB:(o-s)/2**20,quota:o,usage:s}}}catch(o){window.UserLeap.reportError("Error getting storage estimate",o,{originalMessage:e,originalError:t})}Nt(e,t,{reportError:n,extraInfo:r})},U=(e,t,{reportError:n}={reportError:!0})=>(De(),ee(`${e} - ${JSON.stringify(t)}`),_t(e,t,{reportError:n})),v=async(e,t)=>{try{await e()}catch(n){U(t,n)}},Lt=()=>{g.isRecording&&v(()=>{var e,t;return(t=(e=window.rrwebRecord)==null?void 0:e.takeFullSnapshot)==null?void 0:t.call(e,!0)},"Error recording full snapshot")},Mt=async({surveyId:e,responseGroupUuid:t,eventDigest:n,headers:a})=>{if(!e||!t)return!1;const r=window.UserLeap._API_URL,o=await oe({surveyId:e,responseGroupUuid:t,eventDigest:n,apiUrl:r,headers:a},!0);return!(o!=null&&o.error)},Se=30,Ot=1;G("replayStorage").catch(console.error),G("sprig.replay").catch(console.error);class jt{openDB(){return Ze("sprigReplay",Ot,{upgrade:(t,n,a)=>{if(a===0&&m.setItem("sprig.pendingCount","0"),!t.objectStoreNames.contains("events")){const r=t.createObjectStore("events",{keyPath:"uuid"});r.createIndex("sessionId","sessionId"),r.createIndex("timestamp","timestamp"),r.createIndex("[sessionId+timestamp]",["sessionId","timestamp"])}if(!t.objectStoreNames.contains("chunkUploads")){const r=t.createObjectStore("chunkUploads",{keyPath:"uuid"});r.createIndex("sessionId","sessionId"),r.createIndex("timestamp","timestamp"),r.createIndex("[sessionId+status]",["sessionId","status"]),r.createIndex("[uploadId+status]",["uploadId","status"]),r.createIndex("[sessionId+status+uploadId]",["sessionId","status","uploadId"])}if(!t.objectStoreNames.contains("pendingCaptures")){const r=t.createObjectStore("pendingCaptures",{keyPath:"uuid"});r.createIndex("sessionId","sessionId"),r.createIndex("timestamp","timestamp"),r.createIndex("[sessionId+targetTimestamp]",["sessionId","targetTimestamp"])}}})}constructor(){this.openDB().catch(t=>{ee(`Error opening replay storage: ${t.message}`),be(),t.name==="VersionError"&&G("sprigReplay").catch(console.error)})}async bulkAdd(t,n){const a=(await this.openDB()).transaction(t,"readwrite");return Promise.all([...n.map(r=>a.store.add(r)),a.done])}async clearAll(){const t=(await this.openDB()).transaction(["events","chunkUploads","pendingCaptures"],"readwrite");return Promise.all([t.objectStore("events").clear(),t.objectStore("chunkUploads").clear(),t.objectStore("pendingCaptures").clear()])}async deleteBySessionId(t,n){const a=IDBKeyRange.only(n),r=(await this.openDB()).transaction(t,"readwrite");let o=await r.store.index("sessionId").openCursor(a);for(;o;)o.delete(),o=await o.continue();await r.done}async updatePartial(t,n,a){const r=(await this.openDB()).transaction(t,"readwrite"),o=await r.store.get(n);o&&await r.store.put({...o,...a}),await r.done}async deleteRowsBefore(t,n,a=()=>!0){const r=IDBKeyRange.upperBound(n,!0),o=(await this.openDB()).transaction(t,"readwrite");let s=await o.store.index("timestamp").openCursor(r);for(;s;)a(s.value)&&s.delete(),s=await s.continue();await o.done}async getEventsBetween(t,n=Date.now()){if(t>=n)return Promise.resolve([]);const a=IDBKeyRange.bound([w,t],[w,n],!1,!0);return(await this.openDB()).getAllFromIndex("events","[sessionId+timestamp]",a)}async updateEventsExpiredAt(t,n,a=Se){const r=new Date,o=r.setMinutes(r.getMinutes()+(a??Se)),s=(await this.openDB()).transaction("events","readwrite"),d=s.store.index("[sessionId+timestamp]"),l=IDBKeyRange.bound([w,t],[w,n],!1,!0);let u=await d.openCursor(l);for(;u;)u.update({...u.value,expiredAt:o}),u=await u.continue();await s.done}async deleteChunkUploads(t,n){const a=IDBKeyRange.only([n,t]),r=(await this.openDB()).transaction("chunkUploads","readwrite");let o=await r.store.index("[uploadId+status]").openCursor(a);for(;o;)o.delete(),o=await o.continue();await r.done}async getChunkUploadsByStatus({sessionId:t,status:n,uploadId:a}){const r=(await this.openDB()).transaction("chunkUploads","readonly"),o=a?r.store.index("[uploadId+status]"):r.store.index("[sessionId+status]"),s=a?IDBKeyRange.only([a,n]):IDBKeyRange.only([t,n]);return o.getAll(s)}async getPendingCaptures(t={}){return(await(await this.openDB()).getAllFromIndex("pendingCaptures","sessionId",w)).filter(n=>!t.beforePresent||n.targetTimestamp<Date.now()).filter(n=>!t.isHeatmap||(n.captureParams.isHeatmap??!1))}async markPendingCaptureToCanUpload(t){const n=(await this.openDB()).transaction("pendingCaptures","readwrite");let a=await n.store.index("sessionId").openCursor(w);for(;a;){const r=a.value;r.captureParams.responseGroupId===t&&a.update({...r,canUpload:!0}),a=await a.continue()}await n.done}async markPendingHeatmapsReady(t){if(parseInt(m.getItem("sprig.pendingCount")??"0")===0)return null;const n=Date.now(),a=(await this.openDB()).transaction("pendingCaptures","readwrite");let r=await a.store.index("sessionId").openCursor(w);for(;r;){const o=r.value;o.captureParams.isHeatmap&&(!t||t.includes(o.uuid))&&r.update({...o,targetTimestamp:n,captureParams:{...o.captureParams,triggerTimestamp:n,replayParams:{...o.captureParams.replayParams,replayDurationSeconds:Math.floor((n-o.timestamp)/1e3)}}}),r=await r.continue()}await a.done}}const p=new jt,Ht=async(e,t,n)=>new Promise((a,r)=>{const o=e.createElement("script");o.src=t,o.onload=a,o.onerror=r,n&&(o.nonce=n),e.head.appendChild(o)}),ke=async(e,t)=>{const n=performance.now();let a;try{a=await e()}finally{const r=performance.now()-n;let o=te[t];o||(o=ne(t)),o.report(r/1e3)}return a},Ee=(e,t)=>{const n=performance.now();try{e()}finally{const a=performance.now()-n;let r=te[t];r||(r=ne(t)),r.report(a/1e3)}};let Ce=1,z=5e3,A=6e4;const Pe=1e3,Ft=5,xe=30,N=xe+Ft;let Re=Date.now(),k,q=!!m.getItem("sprig.isCapturingHeatmap"),J=!1,Q=[];const Gt=async({viewDocument:e,maxReplayDurationSeconds:t,replayNonce:n,maxInflightRequests:a=2,replaySettings:r,teardownAfter:o=!1})=>{k=m.getItem("sprig.pendingCount"),!g.isRecording&&(o&&m.setItem("sprig.teardownAfterCapture","true"),await v(async()=>{if(E()){i("Not initializing replay because recording is disabled");return}if(!t){i("Not initializing replay because config didn't specify maxReplayDurationSeconds");return}if(r!=null&&r.minAvailableGb&&(Ce=r.minAvailableGb),!await It(Ce)){ae("Minimum storage not available");return}if(i("Initializing replay"),r!=null&&r.minDuration&&(z=r.minDuration),r!=null&&r.batchDuration&&(A=r.batchDuration),Ke(a),Xt(),zt(t+N,30*60,t+N),qt(),!window.rrwebRecord){i("Loading recording script");const u=window.UserLeap.replayLibraryURL??"https://cdn.sprig.com/dependencies/record-2.0.0-alpha.6.min.js";await Ht(e,u,n),i("Recording script finished loading")}const s=window.rrwebRecord;if(!s){ae("Record script failed to set global function");return}let d=!0,l=0;g.stopRecording=s({checkoutEveryNms:xe*1e3,sampling:{input:"last",scroll:250,media:800},emit:(u,c)=>{if(E())return;if(Re=Date.now(),c&&u.type===$.Meta)l=performance.now();else if(c&&l&&u.type===$.FullSnapshot){const h=performance.now()-l;Fe("sdk_replay_snapshot_seconds",h/1e3)}const y=d||!!c&&u.type===$.Meta;d=!1,Wt({uuid:P(),event:JSON.stringify(u),isValidStart:y,timestamp:Date.now()})},...r}),g.isRecording=!!g.stopRecording,g.isRecording&&(g.noopInterval||(g.noopInterval=window.setInterval(()=>{Date.now()-Re>Pe&&I("Sprig_Noop",{})},Pe)),x.on("survey.complete",u=>{Pt({id:u,userAgent:window.navigator.userAgent})}),wt())},"Error initializing replay"))},Wt=e=>{var t,n,a,r;if((t=e.event)!=null&&t.includes("Sprig_Scroll")){const o=(r=(a=(n=JSON.parse(e.event))==null?void 0:n.data)==null?void 0:a.payload)==null?void 0:r.xPath;if(!o)return;g.scrollEventUuids[o]=e.uuid}Q.push(e),J||Vt()},Kt=async e=>{const t=e.map(n=>({...n,sessionId:n.sessionId??w}));if(q&&Dt(t.length),t.length!==0)return v(()=>p.bulkAdd("events",t),"Error storing replay events")},Vt=()=>{J=!0,setTimeout(async()=>{if(E())return;const e=Q;Q=[],J=!1,Ee(async()=>{await Kt(e)},"sdk_replay_add_event_batch_seconds")},500)},zt=(e,t,n)=>{g.cleanupInterval=window.setInterval(()=>{const a=Date.now();E()||(R(`Performing periodic replay data cleanup / Event Seconds ${e} / Chunk Seconds ${t} / Pending Capture Seconds ${n}`),ke(()=>v(async()=>{await Promise.all([p.deleteRowsBefore("events",a-e*1e3,r=>r.expiredAt===void 0||r.expiredAt<a-e*1e3),p.deleteRowsBefore("chunkUploads",a-t*1e3),p.deleteRowsBefore("pendingCaptures",a-n*1e3,r=>!r.canUpload)])},"Error deleting table rows"),"sdk_replay_cleanup_seconds"),i("Cleanup complete"))},3e4)},qt=()=>{g.pendingCheckInterval=window.setInterval(async()=>{v(async()=>{const e=parseInt(k??"0");if(e===0)return;const t=await p.getPendingCaptures({beforePresent:!0}),n=await p.openDB();await Promise.all(t.map(async a=>(await n.delete("pendingCaptures",a.uuid),Ae(a.captureParams,a.canUpload)))),k=(e-t.length).toString(),m.setItem("sprig.pendingCount",k)},"Error initiating pending captures")},5e3)},Jt=async(e,t,n,a,r)=>{const o=Math.min(e+r,n),s=`from: ${new Date(e).toLocaleTimeString()} to ${new Date(o).toLocaleTimeString()}`;i(`Getting event batch ${s}`);const d=await ke(()=>p.getEventsBetween(e,o),"sdk_replay_get_events_between_seconds");if(!(d!=null&&d.length))return i(`No events found ${s}`),{validStartFound:a,events:[]};if(!a){i(`Searching for valid start in ${d.length} events ${s}`);let l=-1;if(d?.forEach((c,y)=>{if(!c.isValidStart)return;const h=c.timestamp<=t;(l<0||h)&&(l=y)}),l<0)return i(`No valid start found in ${d.length} events ${s}`),{validStartFound:a,events:[]};const u=d[l].timestamp;return i(`Found valid start at: ${new Date(u).toLocaleTimeString()} in events ${s}`),{validStartFound:!0,events:d?.slice(l)}}return{validStartFound:a,events:d}},Qt=(e,t,n)=>{const a=e.length,r=t*1024*1024,o=Math.ceil(a/n),s=Math.max(r,o);i(`Total file bytes: ${a} / target chunk size: ${s}`);const d=[];let l=0;for(;l<a;)d.push(e.slice(l,l+s)),l+=s;return d},$e=e=>Promise.all(e.map(async t=>{const n=await Ve(t);return await p.updatePartial("chunkUploads",t.uuid,{data:null,etag:n,status:"UploadComplete"}),t.uploadId})),Be=async e=>{i(`Marking upload complete if finished: ${e}`);const t=await p.getChunkUploadsByStatus({status:"UploadComplete",uploadId:e});if(!(t!=null&&t.length)){i(`No finished chunks found for upload: ${e}`);return}const n=t.reduce((o,s)=>(o.find(d=>d.chunkIndex===s.chunkIndex)||o.push(s),o),[]);n.sort((o,s)=>o.chunkIndex-s.chunkIndex);const a=n.map(o=>({ETag:o.etag,PartNumber:o.chunkIndex})).filter(o=>o.ETag!==null),r=n[0];await oe({apiUrl:r.apiUrl,surveyId:r.surveyId,uploadId:e,responseGroupUuid:r.responseGroupId,etags:a,headers:r.completeUploadHeaders,replayDuration:r.replayDuration}),i(`Cleaning up chunks for ${e}`),await p.deleteChunkUploads("UploadComplete",e),i(`Done cleaning up chunks for ${e}`)},Xt=async()=>{v(async()=>{const e=await p.getChunkUploadsByStatus({sessionId:w,status:"ReadyForUpload"});if(!(e!=null&&e.length))return;const t=await $e(e);i(`Finished uploading unfinished chunks for ${t}`),t!=null&&t.length&&await Promise.all(t.map(n=>{if(n)return Be(n)}))},"Error uploading unfinished chunks")},Yt=async(e,t)=>{await $e(t),i(`Done uploading chunks for uploads: ${e.join(",")}`),await Promise.all(e.map(n=>Be(n)))},Zt=e=>{let t=0;e.forEach(r=>{t+=r.length});const n=new Uint8Array(t);let a=0;return e.forEach(r=>{n.set(r,a),a+=r.length}),n},Te=async(e,t,n)=>{const a=new TextEncoder;let r=null,o=null,s=null,d=!1,l=!1,[u,c]=[0,0];const y=e-N*1e3,h=[];let f=[];i(`Getting events between ${new Date(e).toLocaleTimeString()} and ${new Date(t).toLocaleTimeString()}`),i(`Using batch duration: ${A}ms`);for(let _=y;_<t;_+=A){if({validStartFound:l,events:f}=await Jt(_,e,t,l,A),!(f!=null&&f.length)){i("No events found");continue}u===0&&(u=f[0].timestamp),c=f[f.length-1].timestamp,i(`Last event time in batch: ${new Date(c).toLocaleTimeString()}`);const Le=`${d?",":"["}${f.map(Me=>Me.event).join(",")}`,X=a.encode(Le);n&&o===null&&(R("Attempting compression"),s=new window.CompressionStream("gzip"),o=s.writable.getWriter()),Ee(()=>{n&&o?o.write(X):h.push(X)},"sdk_replay_compression_seconds"),d=!0}if(c-u<z)return i(`Replay duration is shorter than minimum of ${z}ms / Start:${u} / End:${c}`),null;const b=a.encode("]");return R("Writing final close brace"),o&&s?(o.write(b),o.close(),r=new Uint8Array(await new Response(s.readable).arrayBuffer())):(h.push(b),r=Zt(h)),i("Finished generating file data"),r},en=async(e,t)=>{const n=window.CompressionStream!==void 0;let a=null;const r=t??Date.now(),o=r-e;try{a=await Te(o,r,n)}catch(s){s instanceof Error&&window.UserLeap.reportError("Error compressing replay",s),n&&v(async()=>{await Te(o,r,!1)},"fileData fallback failed")}return a},Ue=async e=>{const{surveyId:t,responseGroupId:n,visitorId:a,apiUrl:r,completeUploadHeaders:o,replayParams:s,triggerTimestamp:d}=e,l=await en(s.replayDurationSeconds*1e3,d);if(l!=null&&l.length)i(`Found file data for survey: ${t}`);else{i(`File data is empty for survey: ${t}`);return}const u=Qt(l,s.minimumChunkSizeMb,s.signedUrls.length);i(`Got ${u.length} chunks for survey: ${t}`);const c=await Promise.all(u.map(async(y,h)=>{const f=P(),b={apiUrl:r,chunkIndex:h+1,completeUploadHeaders:o,etag:null,responseGroupId:n,status:"ReadyForUpload",surveyId:t,timestamp:d,totalChunks:u.length,data:y,uploadId:s.uploadId,uploadUrl:s.signedUrls[h].url,uuid:f,visitorId:a};return i(`Recording chunk upload: ${JSON.stringify({index:b.chunkIndex,surveyId:b.surveyId,uploadId:b.uploadId,size:y.length,id:f},null,2)}`),await(await p.openDB()).add("chunkUploads",{...b,sessionId:b.sessionId??w}),i(`Done creating chunk upload: ${f}`),b}));i(`All chunk records created. Beginning upload for survey: ${t}`),await Yt([s.uploadId],c)},Ae=async(e,t)=>{if(i(`Attempting replay capture: ${JSON.stringify({isStandalone:e.isStandalone,duration:e.replayParams.replayDurationSeconds,type:e.replayParams.replayDurationType,responseGroupId:e.responseGroupId,surveyId:e.surveyId,triggerTimestamp:e.triggerTimestamp,visitorId:e.visitorId},null,2)}`),E())return i(`Replay recording is disabled: ${e.surveyId}`);i(`Replay recording enabled: ${e.surveyId}`);const{isHeatmap:n,isStandalone:a,replayParams:r,triggerTimestamp:o,responseGroupId:s}=e,d=async()=>{setTimeout(()=>x.removeListener(L.QuestionAnswered,d),0),v(async()=>{r.replayDurationType==="before"?await Ue(e):await p.markPendingCaptureToCanUpload(s)},"Error in schedule/capture callback")};v(async()=>{if(r.replayDurationType==="after"||r.replayDurationType==="beforeAndAfter"){!a&&!n&&(i("Attaching QuestionAnswered listener for non-standalone replay"),x.on(L.QuestionAnswered,d)),i(`Scheduling capture for replay of type: ${r.replayDurationType}`),await _e(e);return}if(a||n||t)i(`Proceeding to capture replay for survey: ${e.surveyId} / standalone? ${a} / canUpload? ${t}`),await Ue(e),n&&tn();else{const l=N+r.replayDurationSeconds,u=o-l*1e3,c=o;i(`Setting expiry minutes to ${r.expirationTimeLimitMinutes} for events from ${new Date(u).toLocaleTimeString()} to ${new Date(c).toLocaleTimeString()}`),await p.updateEventsExpiredAt(u,c,r.expirationTimeLimitMinutes),i("Attaching QuestionAnswered listener"),x.on(L.QuestionAnswered,d)}},"Error in scheduling/capturing replay")},tn=async()=>{parseInt(k??"0")||(m.removeItem("sprig.isCapturingHeatmap"),q=!1),m.getItem("sprig.teardownAfterCapture")&&(De(),Ne(),m.removeItem("sprig.teardownAfterCapture"))},Ne=()=>{if(E()){R("Not clearing user data, replay is disabled");return}return Promise.all([p.deleteBySessionId("events",w),p.deleteBySessionId("pendingCaptures",w)]).catch(e=>{U("Error clearing user replay data",e)})},_e=async e=>{i(`Scheduling replay capture: ${JSON.stringify(e)}`);const{isHeatmap:t,surveyId:n}=e,a=await p.getPendingCaptures(),r=a?.filter(d=>d.captureParams.surveyId===n);if(r!=null&&r.length){i(`Pending capture exists for survey: ${n}`);return}t&&(Lt(),q=!0,m.setItem("sprig.isCapturingHeatmap","true"));const o={...e,replayParams:{...e.replayParams}};e.replayParams.replayDurationType==="beforeAndAfter"&&(o.replayParams.replayDurationSeconds*=2),o.replayParams.replayDurationType="before";const s=e.triggerTimestamp+e.replayParams.replayDurationSeconds*1e3;o.triggerTimestamp=s,k=(parseInt(k??"0")+1).toString(),m.setItem("sprig.pendingCount",k),await(await p.openDB()).add("pendingCaptures",{canUpload:!1,captureParams:o,sessionId:w,targetTimestamp:s,timestamp:Date.now(),uuid:P()})},nn=Object.freeze(Object.defineProperty({__proto__:null,RecordEvent:Et,RecordPageView:St,RecordSurveyShown:Ct,_completeSessionReplay:Mt,checkPendingHeatmapsUrl:bt,clearUserReplayData:Ne,disableRecording:U,initializeReplay:Gt,isReplayRecording:Tt,scheduleCapture:_e,scheduleOrCaptureReplay:Ae,tryReplayAction:v},Symbol.toStringTag,{value:"Module"}));Ge(nn);