1 line
24 KiB
Plaintext
1 line
24 KiB
Plaintext
(()=>{"use strict";var e=Object.defineProperty,t=(t,n,s)=>(((t,n,s)=>{n in t?e(t,n,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[n]=s})(t,"symbol"!=typeof n?n+"":n,s),s);const n=e=>({ok:!1,error:e});async function s(e,t,s,i){const r=new URL(t,e),o=JSON.stringify(i),a=(d=fetch,(...e)=>{try{return{ok:!0,data:d(...e)}}catch(e){return{ok:!1,error:e}}})(r.toString(),{method:s,headers:{"Content-Type":"application/json"},body:o});var d;if(!1===a.ok)return n(a.error);const c=await a.data,{data:u}=await c.json();return c.ok?(e=>({ok:!0,data:e}))(u):n({code:"network_error",message:c.statusText,status:c.status,url:r})}class i{constructor(e,t){this.apiHost=e,this.environmentId=t}async create(e){return s(this.apiHost,`/api/v1/client/${this.environmentId}/actions`,"POST",e)}}class r{constructor(e,t){this.apiHost=e,this.environmentId=t}async create(e){return s(this.apiHost,`/api/v1/client/${this.environmentId}/displays`,"POST",e)}async update(e,t){return s(this.apiHost,`/api/v1/client/${this.environmentId}/displays/${e}`,"PUT",t)}}class o{constructor(e,t){this.apiHost=e,this.environmentId=t}async create(e){return s(this.apiHost,`/api/v1/client/${this.environmentId}/people`,"POST",{environmentId:this.environmentId,userId:e})}async update(e,t){return s(this.apiHost,`/api/v1/client/${this.environmentId}/people/${e}`,"POST",t)}}class a{constructor(e,t){this.apiHost=e,this.environmentId=t}async create(e){return s(this.apiHost,`/api/v1/client/${this.environmentId}/responses`,"POST",e)}async update({responseId:e,finished:t,data:n,ttc:i}){return s(this.apiHost,`/api/v1/client/${this.environmentId}/responses/${e}`,"PUT",{finished:t,data:n,ttc:i})}}class d{constructor(e,t){this.apiHost=e,this.environmentId=t}async uploadFile(e,{allowedFileExtensions:t,surveyId:n}={}){if(!(e instanceof Blob&&e instanceof File))throw new Error("Invalid file type. Expected Blob or File, but received "+typeof e);const s={fileName:e.name,fileType:e.type,allowedFileExtensions:t,surveyId:n},i=await fetch(`${this.apiHost}/api/v1/client/${this.environmentId}/storage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!i.ok)throw new Error(`Upload failed with status: ${i.status}`);const r=await i.json(),{data:o}=r,{signedUrl:a,fileUrl:d,signingData:c,presignedFields:u,updatedFileName:l}=o;let g={};if(c){const{signature:t,timestamp:s,uuid:i}=c;g={"X-File-Type":e.type,"X-File-Name":encodeURIComponent(l),"X-Survey-ID":n??"","X-Signature":t,"X-Timestamp":String(s),"X-UUID":i}}const p=new FormData;u&&Object.keys(u).forEach((e=>{p.append(e,u[e])})),p.append("file",e);const h=await fetch(a,{method:"POST",...c?{headers:g}:{},body:p});if(!h.ok){if(c){const e=await h.json(),t=new Error(e.message);throw t.name="FileTooLargeError",t}const e=await h.text();if(u&&e&&e.includes("EntityTooLarge")){const e=new Error("File size exceeds the size limit for your plan");throw e.name="FileTooLargeError",e}throw new Error(`Upload failed with status: ${h.status}`)}return d}}class c{constructor(e){const{apiHost:t,environmentId:n}=e;this.response=new a(t,n),this.display=new r(t,n),this.action=new i(t,n),this.people=new o(t,n),this.storage=new d(t,n)}}class u{constructor(e){this.client=new c(e)}}class l{constructor(){this.logLevel="error"}static getInstance(){return l.instance||(l.instance=new l),l.instance}configure(e){e&&void 0!==e.logLevel&&(this.logLevel=e.logLevel)}logger(e,t){if("debug"===t&&"debug"!==this.logLevel)return;const n=`🧱 Formbricks - ${(new Date).toISOString()} [${t.toUpperCase()}] - ${e}`;"error"===t?console.error(n):console.log(n)}debug(e){this.logger(e,"debug")}error(e){this.logger(e,"error")}}const g=e=>({ok:!0,value:e}),p=e=>({ok:!1,error:e}),h=e=>(...t)=>{try{return{ok:!0,value:e(...t)}}catch(e){return{ok:!1,error:e}}},v=l.getInstance(),f=class e{constructor(e){this.customized=!1,e?(this.handleError=e,this.customized=!0):this.handleError=e=>l.getInstance().error(JSON.stringify(e))}static getInstance(){return e.instance||(e.instance=new e),e.instance}static init(t){this.initialized=!0,e.instance=new e(t)}printStatus(){v.debug("Custom error handler: "+(this.customized?"yes":"no"))}handle(e){console.warn("🧱 Formbricks - Global error: ",e),this.handleError(e)}};f.initialized=!1;let w=f;const y="formbricks-js";class m{constructor(){this.config=null;const e=this.loadFromLocalStorage();e.ok&&(this.config=e.value)}static getInstance(){return m.instance||(m.instance=new m),m.instance}update(e){if(e){const t=new Date((new Date).getTime()+12e4);this.config={...this.config,...e,expiresAt:t},this.saveToLocalStorage()}}get(){if(!this.config)throw new Error("config is null, maybe the init function was not called?");return this.config}loadFromLocalStorage(){if("undefined"!=typeof window){const e=localStorage.getItem(y);if(e){const t=JSON.parse(e);return t.expiresAt&&new Date(t.expiresAt)<=new Date?p(new Error("Config in local storage has expired")):g(JSON.parse(e))}}return p(new Error("No or invalid config in local storage"))}saveToLocalStorage(){return h((()=>localStorage.setItem(y,JSON.stringify(this.config))))()}resetConfig(){return this.config=null,h((()=>localStorage.removeItem(y)))()}}const I=(e,t)=>{const n=Math.abs(t.getTime()-e.getTime());return Math.floor(n/864e5)},b=()=>window.location.search.includes("formbricksDebug=true"),k=m.getInstance(),S=l.getInstance();let E=null;const H=async(e,t=!1)=>{var n;try{const s=await(async({apiHost:e,environmentId:t,userId:n},s)=>{const i=`${e}/api/v1/client/${t}/in-app/sync`,r="?version=1.6.0";let o={};if((s||b())&&(o.cache="no-cache",S.debug("No cache option set for sync")),!n){const e=i+r,t=await fetch(e,o);if(!t.ok){const n=await t.json();return p({code:"network_error",status:t.status,message:"Error syncing with backend",url:e,responseMessage:n.message})}return g((await t.json()).data)}const a=`${i}/${n}${r}`,d=await fetch(a,o);if(!d.ok){const e=await d.json();return p({code:"network_error",status:d.status,message:"Error syncing with backend",url:a,responseMessage:e.message})}const c=await d.json(),{data:u}=c;return g(u)})(e,t);if(!0!==(null==s?void 0:s.ok))throw S.error(`Sync failed: ${JSON.stringify(s.error)}`),s.error;let i;try{i=k.get().state}catch(e){}let r={surveys:s.value.surveys,noCodeActionClasses:s.value.noCodeActionClasses,product:s.value.product,attributes:(null==(n=s.value.person)?void 0:n.attributes)||{}};if(e.userId){const e=r.surveys.map((e=>e.name));S.debug("Fetched "+e.length+" surveys during sync: "+e.join(", "))}else{r={...r,displays:(null==i?void 0:i.displays)||[]},r=C(r);const e=r.surveys.map((e=>e.name));S.debug("Fetched "+e.length+" surveys during sync: "+e.join(", "))}k.update({apiHost:e.apiHost,environmentId:e.environmentId,userId:e.userId,state:r})}catch(e){throw S.error(`Error during sync: ${e}`),e}},C=e=>{const{displays:t,product:n}=e;let{surveys:s}=e;if(!t)return e;let i=s.filter((e=>{if("respondMultiple"===e.displayOption)return!0;if("displayOnce"===e.displayOption)return 0===t.filter((t=>t.surveyId===e.id)).length;if("displayMultiple"===e.displayOption)return 0===t.filter((t=>t.surveyId===e.id&&t.responded)).length;throw Error("Invalid displayOption")}));const r=t.length>0?t[t.length-1]:void 0;return i=i.filter((e=>{if(r){if(null!==e.recontactDays){const n=t.filter((t=>t.surveyId===e.id))[0];return!n||I(new Date,new Date(n.createdAt))>=e.recontactDays}return null===n.recontactDays||I(new Date,new Date(r.createdAt))>=n.recontactDays}return!0})),{...e,surveys:i}},$=()=>{"undefined"!=typeof window&&null!==E&&(window.clearInterval(E),E=null)},A=e=>new Promise((t=>setTimeout(t,e)));class L{constructor(e,n){t(this,"queue",[]),t(this,"config"),t(this,"surveyState"),t(this,"isRequestInProgress",!1),t(this,"api"),this.config=e,this.surveyState=n,this.api=new u({apiHost:e.apiHost,environmentId:e.environmentId})}add(e){this.surveyState.accumulateResponse(e),this.config.setSurveyState&&this.config.setSurveyState(this.surveyState),this.queue.push(e),this.processQueue()}async processQueue(){if(this.isRequestInProgress)return;if(0===this.queue.length)return;this.isRequestInProgress=!0;const e=this.queue[0];let t=0;for(;t<this.config.retryAttempts;){if(await this.sendResponse(e)){this.queue.shift();break}console.error("Formbricks: Failed to send response. Retrying...",t),await A(1e3),t++}t>=this.config.retryAttempts?(console.error("Failed to send response after 2 attempts."),this.config.onResponseSendingFailed&&this.config.onResponseSendingFailed(e),this.isRequestInProgress=!1):(this.isRequestInProgress=!1,this.processQueue())}async sendResponse(e){try{if(null!==this.surveyState.responseId)await this.api.client.response.update({...e,responseId:this.surveyState.responseId});else{const t=await this.api.client.response.create({...e,surveyId:this.surveyState.surveyId,userId:this.surveyState.userId||null,singleUseId:this.surveyState.singleUseId||null});if(!t.ok)throw new Error("Could not create response");if(this.surveyState.displayId)try{await this.api.client.display.update(this.surveyState.displayId,{responseId:t.data.id})}catch(e){console.error("Failed to update display, proceeding with the response.",e)}this.surveyState.updateResponseId(t.data.id),this.config.setSurveyState&&this.config.setSurveyState(this.surveyState)}return!0}catch(e){return console.error(e),!1}}updateSurveyState(e){this.surveyState=e}}class F{constructor(e,n,s,i){t(this,"responseId",null),t(this,"displayId",null),t(this,"userId",null),t(this,"surveyId"),t(this,"responseAcc",{finished:!1,data:{},ttc:{}}),t(this,"singleUseId"),this.surveyId=e,this.userId=i??null,this.singleUseId=n??null,this.responseId=s??null}setSurveyId(e){this.surveyId=e,this.clear()}copy(){const e=new F(this.surveyId,this.singleUseId??void 0,this.responseId??void 0,this.userId??void 0);return e.responseId=this.responseId,e.responseAcc=this.responseAcc,e}updateResponseId(e){this.responseId=e}updateDisplayId(e){this.displayId=e}updateUserId(e){this.userId=e}accumulateResponse(e){this.responseAcc={finished:e.finished,ttc:e.ttc,data:{...this.responseAcc.data,...e.data}}}isResponseFinished(){return this.responseAcc.finished}clear(){this.responseId=null,this.responseAcc={finished:!1,data:{},ttc:{}}}}const O=F,U="formbricks-web-container",D=m.getInstance(),P=l.getInstance(),T=w.getInstance();let x=!1,N=e=>{};const R=async e=>{if(x)return void P.debug("A survey is already running. Skipping.");x=!0,e.delay&&P.debug(`Delaying survey by ${e.delay} seconds.`);const t=D.get().state.product,n=new O(e.id,null,null,D.get().userId),s=new L({apiHost:D.get().apiHost,environmentId:D.get().environmentId,retryAttempts:2,onResponseSendingFailed:()=>{N(!0)}},n),i=e.productOverwrites??{},r=i.brandColor??t.brandColor,o=i.highlightBorderColor??t.highlightBorderColor,a=i.clickOutsideClose??t.clickOutsideClose,d=i.darkOverlay??t.darkOverlay,c=i.placement??t.placement,l=t.inAppSurveyBranding,g=await M();setTimeout((()=>{g.renderSurveyModal({survey:e,brandColor:r,isBrandingEnabled:l,clickOutside:a,darkOverlay:d,highlightBorderColor:o,placement:c,getSetIsError:e=>{N=e},onDisplay:async()=>{const{userId:t}=D.get();if(!t){const t={createdAt:new Date,surveyId:e.id,responded:!1},n=D.get().state.displays,s=n?[...n,t]:[t],i=D.get();let r=C({...i.state,displays:s});D.update({...i,state:r})}const i=new u({apiHost:D.get().apiHost,environmentId:D.get().environmentId}),r=await i.client.display.create({surveyId:e.id,userId:t});if(!r.ok)throw new Error("Could not create display");const{id:o}=r.data;n.updateDisplayId(o),s.updateSurveyState(n)},onResponse:e=>{const{userId:t}=D.get();if(!t){const e=D.get().state.displays,t=e&&e[e.length-1];if(!t)throw new Error("No lastDisplay found");if(!t.responded){t.responded=!0;const n=D.get();let s=C({...n.state,displays:e});D.update({...n,state:s})}}t&&n.updateUserId(t),s.updateSurveyState(n),s.add({data:e.data,ttc:e.ttc,finished:e.finished})},onClose:z,onFileUpload:async(e,t)=>{const n=new u({apiHost:D.get().apiHost,environmentId:D.get().environmentId});return await n.client.storage.uploadFile(e,t)},onRetry:()=>{N(!1),s.processQueue()}})}),1e3*e.delay)},z=async()=>{var e;if(null==(e=document.getElementById(U))||e.remove(),j(),!D.get().userId){const e=D.get().state,t=C(e);return D.update({...D.get(),state:t}),void(x=!1)}try{await H({apiHost:D.get().apiHost,environmentId:D.get().environmentId,userId:D.get().userId},!0),x=!1}catch(e){T.handle(e)}},j=()=>{const e=document.createElement("div");e.id=U,document.body.appendChild(e)},M=()=>new Promise(((e,t)=>{if(window.formbricksSurveys)e(window.formbricksSurveys);else{const n=document.createElement("script");n.src="https://unpkg.com/@formbricks/surveys@^1.6.0/dist/index.umd.js",n.async=!0,n.onload=()=>e(window.formbricksSurveys),n.onerror=e=>{console.error("Failed to load Formbricks Surveys library:",e),t(e)},document.head.appendChild(n)}})),q=l.getInstance(),_=m.getInstance(),B=["Exit Intent (Desktop)","50% Scroll"],J=async e=>{var t;const{userId:n,state:{surveys:s=[]}}=_.get();s.forEach((async t=>{const{inlineTriggers:n}=t,{codeConfig:s}=n??{};e!==(null==s?void 0:s.identifier)||await R(t)}));const i={environmentId:_.get().environmentId,userId:n,name:e};if(n&&!B.includes(e)){q.debug(`Sending action "${e}" to backend`);const t=new u({apiHost:_.get().apiHost,environmentId:_.get().environmentId}),s=await t.client.action.create({...i,userId:n});if(!s.ok)return p({code:"network_error",message:`Error tracking action ${e}`,status:500,url:`${_.get().apiHost}/api/v1/client/${_.get().environmentId}/actions`,responseMessage:s.error.message});b()&&await H({environmentId:_.get().environmentId,apiHost:_.get().apiHost,userId:n},!0)}q.debug(`Formbricks: Action "${e}" tracked`);const r=null==(t=_.get().state)?void 0:t.surveys;return r&&r.length>0?await X(e,r):q.debug("No active surveys to display"),{ok:!0,value:void 0}},X=async(e,t)=>{for(const s of t)if(!s.displayPercentage||(n=s.displayPercentage,Math.floor(100*Math.random())+1<=n)){for(const t of s.triggers)if(t===e)return q.debug(`Formbricks: survey ${s.id} triggered by action "${e}"`),void await R(s)}else q.debug("Survey display skipped based on displayPercentage.");var n},Q=e=>async(...t)=>{try{return{ok:!0,data:await e(...t)}}catch(e){return{ok:!1,error:e}}};let W=!1,Y=async function(e){if(e.clientY<=0){const e=await J("Exit Intent (Desktop)");if(!0!==e.ok)return p(e.error)}};const G=()=>{W&&(document.removeEventListener("mouseleave",Y),W=!1)};let K=!1,V=!1,Z=async()=>{const e=window.scrollY,t=window.innerHeight,n=document.documentElement.scrollHeight;if(0===e&&(V=!1),!V&&e/(n-t)>=.5){V=!0;const e=await J("50% Scroll");if(!0!==e.ok)return p(e.error)}};const ee=()=>{K&&(window.removeEventListener("scroll",Z),K=!1)},te=m.getInstance(),ne=l.getInstance(),se=w.getInstance(),ie=async()=>{var e;ne.debug(`Checking page url: ${window.location.href}`);const{state:t}=te.get(),{noCodeActionClasses:n=[],surveys:s=[]}=t??{},i=n.filter((e=>{const{innerHtml:t,cssSelector:n,pageUrl:s}=e.noCodeConfig||{};return s&&!t&&!n})),r=s.filter((e=>{var t;const{pageUrl:n,cssSelector:s,innerHtml:i}=(null==(t=e.inlineTriggers)?void 0:t.noCodeConfig)||{};return n&&!s&&!i}));if(i.length>0)for(const t of i){if(!(null==(e=t.noCodeConfig)?void 0:e.pageUrl))continue;const{noCodeConfig:{pageUrl:n}}=t,s=de(window.location.href,n.value,n.rule);if(!0!==s.ok)return p(s.error);if(!1===s.value)continue;const i=await J(t.name);if(!0!==i.ok)return p(i.error)}return r.length>0&&r.forEach((e=>{const{noCodeConfig:t}=e.inlineTriggers??{},{pageUrl:n}=t??{};if(n){const t=de(window.location.href,n.value,n.rule);if(!0!==t.ok)return p(t.error);R(e)}})),{ok:!0,value:void 0}};let re=!1;const oe=()=>ie(),ae=()=>{"undefined"!=typeof window&&re&&(window.removeEventListener("hashchange",oe),window.removeEventListener("popstate",oe),window.removeEventListener("pushstate",oe),window.removeEventListener("replacestate",oe),window.removeEventListener("load",oe),re=!1)};function de(e,t,n){switch(n){case"exactMatch":return g(e===t);case"contains":return g(e.includes(t));case"startsWith":return g(e.startsWith(t));case"endsWith":return g(e.endsWith(t));case"notMatch":return g(e!==t);case"notContains":return g(!e.includes(t));default:return p({code:"invalid_match_type",message:"Invalid match type"})}}const ce=(e,t)=>{var n,s,i,r,o,a,d,c;const u=null==(s=null==(n=t.noCodeConfig)?void 0:n.innerHtml)?void 0:s.value,l=null==(r=null==(i=t.noCodeConfig)?void 0:i.cssSelector)?void 0:r.value,g=null==(a=null==(o=t.noCodeConfig)?void 0:o.pageUrl)?void 0:a.value,p=null==(c=null==(d=t.noCodeConfig)?void 0:d.pageUrl)?void 0:c.rule;if(!u&&!l&&!g)return!1;if(u&&e.innerHTML!==u)return!1;if(l){const t=l.split(/\s*(?=[.#])/);for(let n of t)if(!e.matches(n))return!1}if(g&&p){const e=de(window.location.href,g,p);if(!e.ok||!e.value)return!1}return!0};let ue=!1;const le=e=>(e=>{const{state:t}=te.get();if(!t)return;const{noCodeActionClasses:n}=t;if(!n)return;const s=e.target;n.forEach((e=>{ce(s,e)&&J(e.name).then((e=>{var t,n;n=e=>{se.handle(e)},!0===(t=e).ok?t.value:n(t.error)}))}));const i=t.surveys;i&&0!==i.length&&i.forEach((e=>{const{inlineTriggers:t}=e;t&&ce(s,t)&&R(e)}))})(e),ge=()=>{ue&&(document.removeEventListener("click",le),ue=!1)};let pe=!1;const he=m.getInstance(),ve=l.getInstance(),fe=async()=>(ve.error("'setUserId' is no longer supported. Please set the userId in the init call instead."),{ok:!0,value:void 0}),we=async(e,t)=>{if(ve.debug("Setting attribute: "+e+" to value: "+t),((e,t)=>he.get().state.attributes[e]===t)(e,t.toString()))return ve.debug("Attribute already set to this value. Skipping update."),{ok:!0,value:void 0};const n=await(async(e,t)=>{const{apiHost:n,environmentId:s,userId:i}=he.get();if(!i)return p({code:"missing_person",message:"Unable to update attribute. User identification deactivated. No userId set."});const r={attributes:{[e]:t}},o=new u({apiHost:n,environmentId:s}),a=await o.client.people.update(i,r);return a.ok?(a.data.changed&&(ve.debug("Attribute updated. Syncing..."),await H({environmentId:s,apiHost:n,userId:i},!0)),{ok:!0,value:void 0}):p({code:"network_error",status:500,message:`Error updating person with userId ${i}`,url:`${he.get().apiHost}/api/v1/client/${s}/people/${i}`,responseMessage:a.error.message})})(e,t.toString());return n.ok?(he.update({environmentId:he.get().environmentId,apiHost:he.get().apiHost,userId:he.get().userId,state:{...he.get().state,attributes:{...he.get().state.attributes,[e]:t.toString()}}}),{ok:!0,value:void 0}):p(n.error)},ye=async()=>{Ee()},me=async()=>{ve.debug("Resetting state & getting new state from backend"),z();const e={environmentId:he.get().environmentId,apiHost:he.get().apiHost,userId:he.get().userId};await ye();try{return await Se(e),{ok:!0,value:void 0}}catch(e){return p(e)}},Ie=m.getInstance(),be=l.getInstance();let ke=!1;const Se=async e=>{if(ke)return be.debug("Already initialized, skipping initialization."),{ok:!0,value:void 0};if(b()&&be.configure({logLevel:"debug"}),w.getInstance().printStatus(),be.debug("Start initialize"),!e.environmentId)return be.debug("No environmentId provided"),p({code:"missing_field",field:"environmentId"});if(!e.apiHost)return be.debug("No apiHost provided"),p({code:"missing_field",field:"apiHost"});if(be.debug("Adding widget container to DOM"),j(),!e.userId&&e.attributes)return be.error("No userId provided but attributes. Cannot update attributes without userId."),p({code:"missing_field",field:"userId"});let t,n=null;if(e.userId&&e.attributes){const t=await(async(e,t,n,s)=>{var i,r;if(!n)return p({code:"missing_person",message:"Unable to update attribute. User identification deactivated. No userId set."});const o={...s};try{const e=null==(r=null==(i=he.get())?void 0:i.state)?void 0:r.attributes;if(e)for(const[t,n]of Object.entries(e))o[t]===n&&delete o[t]}catch(e){ve.debug("config not set; sending all attributes to backend")}if(0===Object.keys(o).length)return ve.debug("No attributes to update. Skipping update."),g(o);ve.debug("Updating attributes: "+JSON.stringify(o));const a={attributes:o},d=new u({apiHost:e,environmentId:t}),c=await d.client.people.update(n,a);return c.ok?g(o):p({code:"network_error",status:500,message:`Error updating person with userId ${n}`,url:`${e}/api/v1/client/${t}/people/${n}`,responseMessage:c.error.message})})(e.apiHost,e.environmentId,e.userId,e.attributes);if(!0!==t.ok)return p(t.error);n=t.value}try{t=Ie.get()}catch(e){be.debug("No existing configuration found.")}return t&&t.state&&t.environmentId===e.environmentId&&t.apiHost===e.apiHost&&t.userId===e.userId&&t.expiresAt?(be.debug("Found existing configuration."),t.expiresAt<new Date?(be.debug("Configuration expired."),await H({apiHost:e.apiHost,environmentId:e.environmentId,userId:e.userId})):(be.debug("Configuration not expired. Extending expiration."),Ie.update(t))):(be.debug("No valid configuration found or it has been expired. Creating new config."),be.debug("Syncing."),await H({apiHost:e.apiHost,environmentId:e.environmentId,userId:e.userId}),await J("New Session")),n&&Object.keys(n).length>0&&Ie.update({environmentId:Ie.get().environmentId,apiHost:Ie.get().apiHost,userId:Ie.get().userId,state:{...Ie.get().state,attributes:{...Ie.get().state.attributes,...e.attributes}}}),be.debug("Adding event listeners"),"undefined"!=typeof window&&null===E&&(E=window.setInterval((async()=>{k.get().expiresAt&&new Date(k.get().expiresAt)>=new Date||(S.debug("Config has expired. Starting sync."),await H({apiHost:k.get().apiHost,environmentId:k.get().environmentId,userId:k.get().userId}))}),3e4)),"undefined"==typeof window||re||(window.addEventListener("hashchange",oe),window.addEventListener("popstate",oe),window.addEventListener("pushstate",oe),window.addEventListener("replacestate",oe),window.addEventListener("load",oe),re=!0),"undefined"==typeof window||ue||(document.addEventListener("click",le),ue=!0),"undefined"==typeof document||W||(document.querySelector("body").addEventListener("mouseleave",Y),W=!0),"undefined"==typeof window||K||(window.addEventListener("load",(()=>{window.addEventListener("scroll",Z)})),K=!0),pe||(window.addEventListener("beforeunload",(()=>{$(),ae(),ge(),G(),ee()})),pe=!0),ke=!0,be.debug("Initialized"),ie(),{ok:!0,value:void 0}},Ee=()=>{be.debug("Deinitializing"),z(),$(),ae(),ge(),G(),ee(),pe&&(window.removeEventListener("beforeunload",(()=>{$(),ae(),ge(),G(),ee()})),pe=!1),Ie.resetConfig(),ke=!1};l.getInstance().debug("Create command queue");const He=new class{constructor(){this.queue=[],this.running=!1,this.resolvePromise=null,this.commandPromise=null}add(e=!0,t,...n){this.queue.push({command:t,checkInitialized:e,commandArgs:n}),this.running||(this.commandPromise=new Promise((e=>{this.resolvePromise=e,this.run()})))}async wait(){this.running&&await this.commandPromise}async run(){for(this.running=!0;this.queue.length>0;){const e=w.getInstance(),t=this.queue.shift();if(!t)continue;if(t.checkInitialized){const t=(be.debug("Check if initialized"),ke&&w.initialized?{ok:!0,value:void 0}:p({code:"not_initialized",message:"Formbricks not initialized. Call initialize() first."}));t&&!0!==t.ok&&e.handle(t.error)}const n=async()=>await(null==t?void 0:t.command.apply(null,null==t?void 0:t.commandArgs)),s=await Q(n)();s&&(s.ok&&s.data&&!s.data.ok&&e.handle(s.data.error),!0!==s.ok&&e.handle(s.error))}this.running=!1,this.resolvePromise&&(this.resolvePromise(),this.resolvePromise=null,this.commandPromise=null)}},Ce=async(e,t)=>{He.add(!0,we,e,t),await He.wait()},$e={init:async e=>{w.init(e.errorHandler),He.add(!1,Se,e),await He.wait()},setUserId:async()=>{He.add(!0,fe),await He.wait()},setEmail:async e=>{Ce("email",e),await He.wait()},setAttribute:Ce,track:async(e,t={})=>{He.add(!0,J,e,t),await He.wait()},logout:async()=>{He.add(!0,ye),await He.wait()},reset:async()=>{He.add(!0,me),await He.wait()},registerRouteChange:async()=>{He.add(!0,ie),await He.wait()},getApi:()=>{const e=m.getInstance(),{environmentId:t,apiHost:n}=e.get();if(!t||!n)throw new Error("formbricks.init() must be called before getApi()");return new u({apiHost:n,environmentId:t})}};document.addEventListener("DOMContentLoaded",(()=>{window.tsdk_formbricks=$e,window.dispatchEvent(new Event("themeisle:survey:loaded"))}))})(); |