@frigade/js 0.2.7 → 0.2.8

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/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- var z=Object.create;var D=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Z=Object.getPrototypeOf,tt=Object.prototype.hasOwnProperty;var et=(e,i)=>{for(var t in i)D(e,t,{get:i[t],enumerable:!0})},M=(e,i,t,s)=>{if(i&&typeof i=="object"||typeof i=="function")for(let o of Q(i))!tt.call(e,o)&&o!==t&&D(e,o,{get:()=>i[o],enumerable:!(s=q(i,o))||s.enumerable});return e};var st=(e,i,t)=>(t=e!=null?z(Z(e)):{},M(i||!e||!e.__esModule?D(t,"default",{value:e,enumerable:!0}):t,e)),it=e=>M(D({},"__esModule",{value:!0}),e);var ct={};et(ct,{Flow:()=>f,Frigade:()=>_});module.exports=it(ct);var J="0.2.7";var B=st(require("cross-fetch"),1),Y=require("uuid");var c={};function R(e){return`${e.__instanceId}-${e.apiKey}:${e.userId??""}:${e.groupId??""}`}var F=class{constructor(i){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:V(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(i).filter(([s,o])=>o!=null));this.config={...this.config,...t}}async fetch(i,t){return K(`${this.config.apiUrl}${i}`,{...t??{},...$(this.config.apiKey)})}getGlobalState(){let i=R(this.config);if(!c[i])throw new Error("Frigade not initialized");return c[i]}};var f=class extends F{constructor(t,s){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.lastUsedVariables={};this.flowDataRaw=s,this.initFromRawData(s)}initFromRawData(t){let s=JSON.parse(t.data),o=s.steps??s.data??[];this.id=t.slug,this.rawData=t,this.configYmlAsJson=s,this.title=this.configYmlAsJson.title,this.subtitle=this.configYmlAsJson.subtitle;let a=this.getUserFlowState();if(!a){console.error(`Flow ${this.id} is not defined in the userFlowStates.`);return}this.userFlowStateRaw=a,this.isCompleted=a.flowState==O,this.isStarted=a.flowState==E,this.isSkipped=a.flowState==U;let r=this.isCompleted||this.isSkipped,d=t.targetingLogic&&a.shouldTrigger===!1;this.isVisible=!r&&!d;let T=new Map;o.forEach((g,P)=>{let I=a.stepStates[g.id],C={...g,isCompleted:I.actionType==m,isStarted:I.actionType==b,isHidden:I.hidden,isBlocked:I.blocked,order:P};C.start=async S=>{let n=this.steps.get(g.id);if(n.isStarted||n.isCompleted)return;n.isStarted=!0;let h=w(this.getGlobalState().userFlowStates[this.id]);h.stepStates[n.id].actionType=b,h.lastStepId=n.id,this.getGlobalState().userFlowStates[this.id]=h,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:n.id,data:S??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState();let p=this.getUserFlowState();n.isCompleted=p.stepStates[n.id].actionType==m,n.isStarted=p.stepStates[n.id].actionType==b},C.complete=async S=>{let n=this.steps.get(g.id);if(n.isCompleted)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size;n.isCompleted=!0,this.isStarted=!0;let l=w(this.getGlobalState().userFlowStates[this.id]);l.stepStates[n.id].actionType=m,l.flowState=p?O:E;let x=Array.from(this.steps.keys())[P+1];x&&(l.lastStepId=x),p&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=l,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:n.id,data:S??{},createdAt:new Date().toISOString(),actionType:m})}),p?await this.complete():await this.refreshUserFlowState();let W=this.getUserFlowState();n.isCompleted=W.stepStates[n.id].actionType==m,n.isStarted=W.stepStates[n.id].actionType==b},C.onStateChange=S=>{let n=h=>{if(h.id!==this.id)return;let p=h.steps.get(g.id),l=this.lastStepUpdate.get(S);(p.isCompleted!==(l==null?void 0:l.isCompleted)||p.isStarted!==(l==null?void 0:l.isStarted)||p.isHidden!==(l==null?void 0:l.isHidden)||p.isBlocked!==(l==null?void 0:l.isBlocked))&&(S(p,l??w(p)),this.lastStepUpdate.set(S,w(p)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(S,n),this.getGlobalState().onFlowStateChangeHandlers.push(n)},C.removeStateChangeHandler=S=>{let n=this.getGlobalState().onStepStateChangeHandlerWrappers.get(S);n&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(h=>h!==n))},T.set(g.id,C)}),this.steps=T,Object.keys(this.lastUsedVariables).length>0&&this.applyVariables(this.lastUsedVariables)}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let s=w(this.getGlobalState().userFlowStates[this.id]);s.flowState=E,this.getGlobalState().userFlowStates[this.id]=s,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:E})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:O})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=w(this.getGlobalState().userFlowStates[this.id]);t.flowState=O,this.getGlobalState().userFlowStates[this.id]=t,this.isVisible=!1}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:U})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,this.getGlobalState().userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:k})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let s=Array.from(this.steps.keys()).find(o=>this.steps.get(o).isCompleted===!1&&this.steps.get(o).isHidden===!1)??Array.from(this.steps.keys())[0];return this.steps.get(s)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>!t.isHidden).length}onStateChange(t){let s=(o,a)=>{(o.id===this.id&&(o.isCompleted!==a.isCompleted||o.isStarted!==a.isStarted||o.isSkipped!==a.isSkipped||o.isVisible!==a.isVisible)||JSON.stringify(o.steps)!==JSON.stringify(a.steps))&&t(o,a)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,s),this.getGlobalState().onFlowStateChangeHandlers.push(s)}removeStateChangeHandler(t){let s=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);s&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(o=>o!==s))}applyVariables(t){let s=o=>{let a=o.match(/\${(.*?)}/g);return a&&a.forEach(r=>{let d=r.replace("${","").replace("}","");o=o.replace(r,t[d]??"")}),o};this.title=s(this.title??""),this.subtitle=s(this.subtitle??""),this.steps.forEach(o=>{Object.keys(o).forEach(a=>{typeof o[a]=="string"&&(o[a]=s(o[a]))})}),this.lastUsedVariables=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var O="COMPLETED_FLOW",U="SKIPPED_FLOW",E="STARTED_FLOW",k="NOT_STARTED_FLOW",m="COMPLETED_STEP",b="STARTED_STEP",at="frigade-last-call-at-",ot="frigade-last-call-data-",j="frigade-guest-key",rt="guest_",v="get-cache-",nt=1e3,lt=1e3,L="fr-js-";function H(e){let i=new f(e.config,e.rawData);return i.isCompleted=e.isCompleted,i.isStarted=e.isStarted,i.isSkipped=e.isSkipped,i.isVisible=e.isVisible,i.steps=e.steps,i}function w(e){return JSON.parse(JSON.stringify(e))}function $(e){return{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","X-Frigade-SDK-Version":J,"X-Frigade-SDK-Platform":"Javascript"}}}function G(e){return u()?window.localStorage.getItem(`${L}${e}`):null}function A(e,i){u()&&window.localStorage.setItem(`${L}${e}`,i)}function dt(e,i){c[e]=i}function pt(e){return c[e]}function N(){Object.keys(c).forEach(e=>{e.startsWith(v)&&delete c[e]})}function X(){u()&&Object.keys(window.localStorage).forEach(e=>{e.startsWith(L)&&window.localStorage.removeItem(e)})}async function K(e,i){let t=at+e,s=ot+e;if(u()&&i&&i.body&&i.method==="POST"){let r=G(t),d=G(s);if(r&&d&&d==i.body){let T=new Date(r);if(new Date().getTime()-T.getTime()<lt)return y()}A(t,new Date().toISOString()),A(s,i.body),N()}let o=(i==null?void 0:i.method)==="GET"||!(i!=null&&i.method);if(o){let r=pt(`${v}${e}`);if(r&&new Date().getTime()-r.timestamp<nt)return r.response}let a;try{if(a=(0,B.default)(e,i),o){let r=a.then(d=>d.clone().json());dt(`${v}${e}`,{response:r,timestamp:new Date().getTime()})}a=await a}catch(r){return y(r)}if(!a)return y("Received an empty response");if(a.status>=400)return y(a.statusText);try{let r=await a.json();return r.error?y(r.error):r}catch(r){return y(r)}}function y(e){return e&&console.log("Call to Frigade failed",e),{json:()=>({})}}function V(){if(u()){let e=G(j);return e||(e=`${rt}${(0,Y.v4)()}`,A(j,e)),e}}function u(){return typeof window<"u"}var _=class extends F{constructor(t,s){super({apiKey:t,...s});this.flows=[];this.init(this.config),u()&&document.addEventListener("visibilitychange",async()=>{document.visibilityState==="visible"&&(await this.refreshFlows(),await this.refreshUserFlowStates())})}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,s){this.config={userId:t},await this.initIfNeeded(),await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:s})}),await this.refreshUserFlowStates()}async group(t,s){await this.initIfNeeded(),this.config.groupId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:s})}),await this.refreshUserFlowStates()}async track(t,s){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,event:t,properties:s})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(s=>s.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){X(),N(),this.initPromise=null,await this.init(this.config)}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}removeStateChangeHandler(t){this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(s=>s!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=R(this.config);if(!c[t]){let s=this,o={set:function(a,r,d){return a[r]&&a[r].flowState&&(JSON.stringify(a[r].flowState)!==JSON.stringify(d.flowState)||JSON.stringify(a[r].stepStates)!==JSON.stringify(d.stepStates)||JSON.stringify(a[r].shouldTrigger)!==JSON.stringify(d.shouldTrigger))&&s.triggerEventHandlers(a[r]),a[r]=d,!0}};c[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},o),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},c[t].refreshUserFlowStates=async()=>{let a=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.groupId?`&foreignUserGroupId=${this.config.groupId}`:""}`);a&&a.data&&a.data.forEach(d=>{c[t].userFlowStates[d.flowId]=d})}}await c[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(o=>{this.flows.push(new f(this.config,o)),this.getGlobalState().previousFlows.set(o.slug,H(this.flows[this.flows.length-1]))})}async triggerEventHandlers(t){t&&this.flows.forEach(s=>{s.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(o=>{let a=this.getGlobalState().previousFlows.get(s.id);o(s,a),this.getGlobalState().previousFlows.set(s.id,H(s))})})}};0&&(module.exports={Flow,Frigade});
2
+ var z=Object.create;var D=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Z=Object.getPrototypeOf,tt=Object.prototype.hasOwnProperty;var et=(e,i)=>{for(var t in i)D(e,t,{get:i[t],enumerable:!0})},M=(e,i,t,s)=>{if(i&&typeof i=="object"||typeof i=="function")for(let a of Q(i))!tt.call(e,a)&&a!==t&&D(e,a,{get:()=>i[a],enumerable:!(s=q(i,a))||s.enumerable});return e};var st=(e,i,t)=>(t=e!=null?z(Z(e)):{},M(i||!e||!e.__esModule?D(t,"default",{value:e,enumerable:!0}):t,e)),it=e=>M(D({},"__esModule",{value:!0}),e);var ct={};et(ct,{Flow:()=>f,Frigade:()=>P});module.exports=it(ct);var J="0.2.8";var B=st(require("cross-fetch"),1),Y=require("uuid");var c={};function R(e){return`${e.__instanceId}-${e.apiKey}:${e.userId??""}:${e.groupId??""}`}var F=class{constructor(i){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:V(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(i).filter(([s,a])=>a!=null));this.config={...this.config,...t}}async fetch(i,t){return K(`${this.config.apiUrl}${i}`,{...t??{},...$(this.config.apiKey)})}getGlobalState(){let i=R(this.config);if(!c[i])throw new Error("Frigade not initialized");return c[i]}};var f=class extends F{constructor(t,s){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.lastUsedVariables={};this.flowDataRaw=s,this.initFromRawData(s)}initFromRawData(t){let s=JSON.parse(t.data),a=s.steps??s.data??[];this.id=t.slug,this.rawData=t,this.configYmlAsJson=s,this.title=this.configYmlAsJson.title,this.subtitle=this.configYmlAsJson.subtitle;let o=this.getUserFlowState();if(!o){console.error(`Flow ${this.id} is not defined in the userFlowStates.`);return}this.userFlowStateRaw=o,this.isCompleted=o.flowState==O,this.isStarted=o.flowState==E,this.isSkipped=o.flowState==v;let r=this.isCompleted||this.isSkipped,d=t.targetingLogic&&o.shouldTrigger===!1;this.isVisible=!r&&!d;let T=new Map;a.forEach((g,G)=>{let I=o.stepStates[g.id],C={...g,isCompleted:I.actionType==m,isStarted:I.actionType==b,isHidden:I.hidden,isBlocked:I.blocked,order:G};C.start=async S=>{let n=this.steps.get(g.id);if(n.isStarted||n.isCompleted)return;n.isStarted=!0;let h=w(this.getGlobalState().userFlowStates[this.id]);h.stepStates[n.id].actionType=b,h.lastStepId=n.id,this.getGlobalState().userFlowStates[this.id]=h,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:n.id,data:S??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState();let p=this.getUserFlowState();n.isCompleted=p.stepStates[n.id].actionType==m,n.isStarted=p.stepStates[n.id].actionType==b},C.complete=async S=>{let n=this.steps.get(g.id);if(n.isCompleted)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size;n.isCompleted=!0,this.isStarted=!0;let l=w(this.getGlobalState().userFlowStates[this.id]);l.stepStates[n.id].actionType=m,l.flowState=p?O:E;let x=Array.from(this.steps.keys())[G+1];x&&(l.lastStepId=x),p&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=l,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:n.id,data:S??{},createdAt:new Date().toISOString(),actionType:m})}),p?await this.complete():await this.refreshUserFlowState();let W=this.getUserFlowState();n.isCompleted=W.stepStates[n.id].actionType==m,n.isStarted=W.stepStates[n.id].actionType==b},C.onStateChange=S=>{let n=h=>{if(h.id!==this.id)return;let p=h.steps.get(g.id),l=this.lastStepUpdate.get(S);(p.isCompleted!==(l==null?void 0:l.isCompleted)||p.isStarted!==(l==null?void 0:l.isStarted)||p.isHidden!==(l==null?void 0:l.isHidden)||p.isBlocked!==(l==null?void 0:l.isBlocked))&&(S(p,l??w(p)),this.lastStepUpdate.set(S,w(p)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(S,n),this.getGlobalState().onFlowStateChangeHandlers.push(n)},C.removeStateChangeHandler=S=>{let n=this.getGlobalState().onStepStateChangeHandlerWrappers.get(S);n&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(h=>h!==n))},T.set(g.id,C)}),this.steps=T,Object.keys(this.lastUsedVariables).length>0&&this.applyVariables(this.lastUsedVariables)}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let s=w(this.getGlobalState().userFlowStates[this.id]);s.flowState=E,this.getGlobalState().userFlowStates[this.id]=s,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:E})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:O})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=w(this.getGlobalState().userFlowStates[this.id]);t.flowState=O,this.getGlobalState().userFlowStates[this.id]=t,this.isVisible=!1}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:v})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,this.getGlobalState().userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:k})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let s=Array.from(this.steps.keys()).find(a=>this.steps.get(a).isCompleted===!1&&this.steps.get(a).isHidden===!1)??Array.from(this.steps.keys())[0];return this.steps.get(s)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>!t.isHidden).length}onStateChange(t){let s=(a,o)=>{(a.id===this.id&&(a.isCompleted!==o.isCompleted||a.isStarted!==o.isStarted||a.isSkipped!==o.isSkipped||a.isVisible!==o.isVisible)||JSON.stringify(a.steps)!==JSON.stringify(o.steps))&&t(a,o)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,s),this.getGlobalState().onFlowStateChangeHandlers.push(s)}removeStateChangeHandler(t){let s=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);s&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(a=>a!==s))}applyVariables(t){let s=a=>{let o=a.match(/\${(.*?)}/g);return o&&o.forEach(r=>{let d=r.replace("${","").replace("}","");a=a.replace(r,t[d]??"")}),a};this.title=s(this.title??""),this.subtitle=s(this.subtitle??""),this.steps.forEach(a=>{Object.keys(a).forEach(o=>{typeof a[o]=="string"&&(a[o]=s(a[o]))})}),this.lastUsedVariables=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var O="COMPLETED_FLOW",v="SKIPPED_FLOW",E="STARTED_FLOW",k="NOT_STARTED_FLOW",m="COMPLETED_STEP",b="STARTED_STEP",at="frigade-last-call-at-",ot="frigade-last-call-data-",j="frigade-guest-key",rt="guest_",U="get-cache-",nt=1e3,lt=1e3,L="fr-js-";function _(e){let i=new f(e.config,e.rawData);return i.isCompleted=e.isCompleted,i.isStarted=e.isStarted,i.isSkipped=e.isSkipped,i.isVisible=e.isVisible,i.steps=e.steps,i}function w(e){return JSON.parse(JSON.stringify(e))}function $(e){return{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","X-Frigade-SDK-Version":J,"X-Frigade-SDK-Platform":"Javascript"}}}function A(e){return u()?window.localStorage.getItem(`${L}${e}`):null}function H(e,i){u()&&window.localStorage.setItem(`${L}${e}`,i)}function dt(e,i){c[e]=i}function pt(e){return c[e]}function N(){Object.keys(c).forEach(e=>{e.startsWith(U)&&delete c[e]})}function X(){u()&&Object.keys(window.localStorage).forEach(e=>{e.startsWith(L)&&window.localStorage.removeItem(e)})}async function K(e,i){let t=at+e,s=ot+e;if(u()&&i&&i.body&&i.method==="POST"){let r=A(t),d=A(s);if(r&&d&&d==i.body){let T=new Date(r);if(new Date().getTime()-T.getTime()<lt)return y()}H(t,new Date().toISOString()),H(s,i.body),N()}let a=(i==null?void 0:i.method)==="GET"||!(i!=null&&i.method);if(a){let r=pt(`${U}${e}`);if(r&&new Date().getTime()-r.timestamp<nt)return r.response}let o;try{if(o=(0,B.default)(e,i),a){let r=o.then(d=>d.clone().json());dt(`${U}${e}`,{response:r,timestamp:new Date().getTime()})}o=await o}catch(r){return y(r)}if(!o)return y("Received an empty response");if(o.status>=400)return y(o.statusText);try{let r=await o.json();return r.error?y(r.error):r}catch(r){return y(r)}}function y(e){return e&&console.log("Call to Frigade failed",e),{json:()=>({})}}function V(){if(u()){let e=A(j);return e||(e=`${rt}${(0,Y.v4)()}`,H(j,e)),e}}function u(){return typeof window<"u"}var P=class extends F{constructor(t,s){super({apiKey:t,...s});this.flows=[];this.init(this.config),u()&&document.addEventListener("visibilitychange",async()=>{document.visibilityState==="visible"&&(await this.refreshFlows(),await this.refreshUserFlowStates())})}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,s){this.config={userId:t},await this.initIfNeeded(),await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:s})}),await this.refreshUserFlowStates()}async group(t,s){await this.initIfNeeded(),this.config.groupId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:s})}),await this.refreshUserFlowStates()}async track(t,s){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,event:t,properties:s})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(s=>s.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reload(){X(),N(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(s=>{let a=this.getGlobalState().previousFlows.get(t.id);s(t,a),this.getGlobalState().previousFlows.set(t.id,_(t))})})}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}removeStateChangeHandler(t){this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(s=>s!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=R(this.config);if(!c[t]){let s=this,a={set:function(o,r,d){return o[r]&&o[r].flowState&&(JSON.stringify(o[r].flowState)!==JSON.stringify(d.flowState)||JSON.stringify(o[r].stepStates)!==JSON.stringify(d.stepStates)||JSON.stringify(o[r].shouldTrigger)!==JSON.stringify(d.shouldTrigger))&&s.triggerEventHandlers(o[r]),o[r]=d,!0}};c[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},a),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},c[t].refreshUserFlowStates=async()=>{let o=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.groupId?`&foreignUserGroupId=${this.config.groupId}`:""}`);o&&o.data&&o.data.forEach(d=>{c[t].userFlowStates[d.flowId]=d})}}await c[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(a=>{this.flows.push(new f(this.config,a)),this.getGlobalState().previousFlows.set(a.slug,_(this.flows[this.flows.length-1]))})}async triggerEventHandlers(t){t&&this.flows.forEach(s=>{s.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(a=>{let o=this.getGlobalState().previousFlows.get(s.id);a(s,o),this.getGlobalState().previousFlows.set(s.id,_(s))})})}};0&&(module.exports={Flow,Frigade});
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/Fetchable.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export { Frigade } from './core/frigade'\nexport { Flow } from './core/flow'\nexport { FlowStep } from './core/flow-step'\n\nexport * from './types'\n","export const VERSION_NUMBER = '0.2.7'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { frigadeGlobalState } from './state'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst GET_CACHE_TTL_MS = 1000\nconst POST_CACHE_TTL_MS = 1000\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow(flow.config, flow.rawData)\n newFlow.isCompleted = flow.isCompleted\n newFlow.isStarted = flow.isStarted\n newFlow.isSkipped = flow.isSkipped\n newFlow.isVisible = flow.isVisible\n newFlow.steps = flow.steps\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n }\n}\n\nfunction setGlobalState(key: string, value: any) {\n frigadeGlobalState[key] = value\n}\n\nfunction getGlobalState(key: string): any {\n return frigadeGlobalState[key]\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (isWeb() && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < POST_CACHE_TTL_MS) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n clearCache()\n }\n\n const isGetCall = options?.method === 'GET' || !options?.method\n if (isGetCall) {\n const cachedResponse = getGlobalState(`${GET_CACHE_PREFIX}${url}`)\n if (cachedResponse) {\n const now = new Date()\n const diff = now.getTime() - cachedResponse.timestamp\n if (diff < GET_CACHE_TTL_MS) {\n return cachedResponse.response\n }\n }\n }\n\n let response\n try {\n response = fetch(url, options)\n if (isGetCall) {\n const responsePromise = response.then((res) => {\n return res.clone().json()\n })\n setGlobalState(`${GET_CACHE_PREFIX}${url}`, {\n response: responsePromise,\n timestamp: new Date().getTime(),\n })\n }\n\n response = await response\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n const body = await response.json()\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n\nexport function isWeb() {\n return typeof window !== 'undefined'\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { Flow } from '../core/flow'\nimport { FlowStep } from '../core/flow-step'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n onFlowStateChangeHandlerWrappers: Map<\n (flow: Flow, previousFlow: Flow) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onStepStateChangeHandlerWrappers: Map<\n (step: FlowStep, previousStep: FlowStep) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[]\n previousFlows: Map<string, Flow>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.groupId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade not initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public configYmlAsJson: any\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public rawData: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n /**\n * Whether the flow has been skipped or not\n */\n public isSkipped: boolean\n /**\n * Whether the flow is visible to the user based on the current user/group's state\n */\n public isVisible: boolean = false\n\n private readonly flowDataRaw: FlowDataRaw\n\n private userFlowStateRaw?: UserFlowState\n\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n private lastUsedVariables = {}\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.rawData = flowDataRaw\n this.configYmlAsJson = flowDataYml\n this.title = this.configYmlAsJson.title\n this.subtitle = this.configYmlAsJson.subtitle\n\n const userFlowState = this.getUserFlowState()\n if (!userFlowState) {\n console.error(`Flow ${this.id} is not defined in the userFlowStates.`)\n return\n }\n this.userFlowStateRaw = userFlowState\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.isSkipped = userFlowState.flowState == SKIPPED_FLOW\n const hasCompleted = this.isCompleted || this.isSkipped\n const targetingShouldHideFlow =\n flowDataRaw.targetingLogic && userFlowState.shouldTrigger === false\n this.isVisible = !hasCompleted && !targetingShouldHideFlow\n const newSteps = new Map<string, FlowStep>()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[currentStep.id].actionType = STARTED_STEP\n copy.lastStepId = currentStep.id\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n currentStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[currentStep.id].actionType = COMPLETED_STEP\n copy.flowState = isLastStep ? COMPLETED_FLOW : STARTED_FLOW\n\n const nextStepId = Array.from(this.steps.keys())[index + 1]\n if (nextStepId) {\n copy.lastStepId = nextStepId\n }\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n // if all steps are now completed, mark flow completed\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n if (isLastStep) {\n await this.complete()\n } else {\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const currentStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n currentStep.isCompleted !== previousStep?.isCompleted ||\n currentStep.isStarted !== previousStep?.isStarted ||\n currentStep.isHidden !== previousStep?.isHidden ||\n currentStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(currentStep, previousStep ?? clone(currentStep))\n this.lastStepUpdate.set(handler, clone(currentStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj)\n })\n this.steps = newSteps\n // Check if empty object\n if (Object.keys(this.lastUsedVariables).length > 0) {\n this.applyVariables(this.lastUsedVariables)\n }\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = STARTED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n private optimisticallyMarkFlowCompleted() {\n this.isStarted = true\n this.isCompleted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = COMPLETED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n this.isVisible = false\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n this.getGlobalState().userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false && this.steps.get(key).isHidden === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => !step.isHidden).length\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (\n (flow.id === this.id &&\n (flow.isCompleted !== previousFlow.isCompleted ||\n flow.isStarted !== previousFlow.isStarted ||\n flow.isSkipped !== previousFlow.isSkipped ||\n flow.isVisible !== previousFlow.isVisible)) ||\n JSON.stringify(flow.steps) !== JSON.stringify(previousFlow.steps)\n ) {\n handler(flow, previousFlow)\n }\n }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n public applyVariables(variables: Record<string, any>) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n str = str.replace(match, variables[variable] ?? '')\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n this.steps.forEach((step) => {\n // Iterate over every string field in the step and replace variables\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n }\n })\n })\n\n this.lastUsedVariables = variables\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { clearCache, cloneFlow, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshFlows()\n await this.refreshUserFlowStates()\n }\n })\n }\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { userId }\n await this.initIfNeeded()\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n clearCache()\n this.initPromise = null\n await this.init(this.config)\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n target[key] &&\n target[key].flowState &&\n (JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState) ||\n JSON.stringify(target[key].stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger))\n ) {\n that.triggerEventHandlers(target[key])\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.groupId ? `&foreignUserGroupId=${this.config.groupId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n this.getGlobalState().previousFlows.set(\n flowData.slug,\n cloneFlow(this.flows[this.flows.length - 1])\n )\n })\n }\n }\n\n private async triggerEventHandlers(previousUserFlowState: UserFlowState) {\n if (previousUserFlowState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousUserFlowState.flowId) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n }\n}\n"],"mappings":"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","names":["src_exports","__export","Flow","Frigade","__toCommonJS","VERSION_NUMBER","import_cross_fetch","import_uuid","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","filteredConfig","_","v","path","options","gracefulFetch","getHeaders","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","hasCompleted","targetingShouldHideFlow","newSteps","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","handler","wrapperHandler","flow","previousStep","NOT_STARTED_FLOW","currentStepId","key","previousFlow","h","variables","replaceVariables","str","matches","match","variable","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","GET_CACHE_TTL_MS","POST_CACHE_TTL_MS","LOCAL_STORAGE_PREFIX","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","setGlobalState","frigadeGlobalState","getGlobalState","clearCache","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","isGetCall","cachedResponse","response","fetch","responsePromise","res","error","body","e","generateGuestId","guestId","uuidv4","isWeb","Frigade","Fetchable","apiKey","config","isWeb","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","cloneFlow","previousUserFlowState","lastFlow"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/Fetchable.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export { Frigade } from './core/frigade'\nexport { Flow } from './core/flow'\nexport { FlowStep } from './core/flow-step'\n\nexport * from './types'\n","export const VERSION_NUMBER = '0.2.8'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { frigadeGlobalState } from './state'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst GET_CACHE_TTL_MS = 1000\nconst POST_CACHE_TTL_MS = 1000\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow(flow.config, flow.rawData)\n newFlow.isCompleted = flow.isCompleted\n newFlow.isStarted = flow.isStarted\n newFlow.isSkipped = flow.isSkipped\n newFlow.isVisible = flow.isVisible\n newFlow.steps = flow.steps\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n }\n}\n\nfunction setGlobalState(key: string, value: any) {\n frigadeGlobalState[key] = value\n}\n\nfunction getGlobalState(key: string): any {\n return frigadeGlobalState[key]\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (isWeb() && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < POST_CACHE_TTL_MS) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n clearCache()\n }\n\n const isGetCall = options?.method === 'GET' || !options?.method\n if (isGetCall) {\n const cachedResponse = getGlobalState(`${GET_CACHE_PREFIX}${url}`)\n if (cachedResponse) {\n const now = new Date()\n const diff = now.getTime() - cachedResponse.timestamp\n if (diff < GET_CACHE_TTL_MS) {\n return cachedResponse.response\n }\n }\n }\n\n let response\n try {\n response = fetch(url, options)\n if (isGetCall) {\n const responsePromise = response.then((res) => {\n return res.clone().json()\n })\n setGlobalState(`${GET_CACHE_PREFIX}${url}`, {\n response: responsePromise,\n timestamp: new Date().getTime(),\n })\n }\n\n response = await response\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n const body = await response.json()\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n\nexport function isWeb() {\n return typeof window !== 'undefined'\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { Flow } from '../core/flow'\nimport { FlowStep } from '../core/flow-step'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n onFlowStateChangeHandlerWrappers: Map<\n (flow: Flow, previousFlow: Flow) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onStepStateChangeHandlerWrappers: Map<\n (step: FlowStep, previousStep: FlowStep) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[]\n previousFlows: Map<string, Flow>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.groupId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade not initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public configYmlAsJson: any\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public rawData: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n /**\n * Whether the flow has been skipped or not\n */\n public isSkipped: boolean\n /**\n * Whether the flow is visible to the user based on the current user/group's state\n */\n public isVisible: boolean = false\n\n private readonly flowDataRaw: FlowDataRaw\n\n private userFlowStateRaw?: UserFlowState\n\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n private lastUsedVariables = {}\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.rawData = flowDataRaw\n this.configYmlAsJson = flowDataYml\n this.title = this.configYmlAsJson.title\n this.subtitle = this.configYmlAsJson.subtitle\n\n const userFlowState = this.getUserFlowState()\n if (!userFlowState) {\n console.error(`Flow ${this.id} is not defined in the userFlowStates.`)\n return\n }\n this.userFlowStateRaw = userFlowState\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.isSkipped = userFlowState.flowState == SKIPPED_FLOW\n const hasCompleted = this.isCompleted || this.isSkipped\n const targetingShouldHideFlow =\n flowDataRaw.targetingLogic && userFlowState.shouldTrigger === false\n this.isVisible = !hasCompleted && !targetingShouldHideFlow\n const newSteps = new Map<string, FlowStep>()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[currentStep.id].actionType = STARTED_STEP\n copy.lastStepId = currentStep.id\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n currentStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[currentStep.id].actionType = COMPLETED_STEP\n copy.flowState = isLastStep ? COMPLETED_FLOW : STARTED_FLOW\n\n const nextStepId = Array.from(this.steps.keys())[index + 1]\n if (nextStepId) {\n copy.lastStepId = nextStepId\n }\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n // if all steps are now completed, mark flow completed\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n if (isLastStep) {\n await this.complete()\n } else {\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const currentStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n currentStep.isCompleted !== previousStep?.isCompleted ||\n currentStep.isStarted !== previousStep?.isStarted ||\n currentStep.isHidden !== previousStep?.isHidden ||\n currentStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(currentStep, previousStep ?? clone(currentStep))\n this.lastStepUpdate.set(handler, clone(currentStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj)\n })\n this.steps = newSteps\n // Check if empty object\n if (Object.keys(this.lastUsedVariables).length > 0) {\n this.applyVariables(this.lastUsedVariables)\n }\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = STARTED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n private optimisticallyMarkFlowCompleted() {\n this.isStarted = true\n this.isCompleted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = COMPLETED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n this.isVisible = false\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n this.getGlobalState().userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false && this.steps.get(key).isHidden === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => !step.isHidden).length\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (\n (flow.id === this.id &&\n (flow.isCompleted !== previousFlow.isCompleted ||\n flow.isStarted !== previousFlow.isStarted ||\n flow.isSkipped !== previousFlow.isSkipped ||\n flow.isVisible !== previousFlow.isVisible)) ||\n JSON.stringify(flow.steps) !== JSON.stringify(previousFlow.steps)\n ) {\n handler(flow, previousFlow)\n }\n }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n public applyVariables(variables: Record<string, any>) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n str = str.replace(match, variables[variable] ?? '')\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n this.steps.forEach((step) => {\n // Iterate over every string field in the step and replace variables\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n }\n })\n })\n\n this.lastUsedVariables = variables\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { clearCache, cloneFlow, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshFlows()\n await this.refreshUserFlowStates()\n }\n })\n }\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { userId }\n await this.initIfNeeded()\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n /**\n * Reload the current state of the flows by calling the Frigade API.\n * This will trigger all event handlers.\n */\n public async reload() {\n resetAllLocalStorage()\n clearCache()\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n this.initPromise = null\n await this.init(this.config)\n // Trigger all event handlers\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n target[key] &&\n target[key].flowState &&\n (JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState) ||\n JSON.stringify(target[key].stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger))\n ) {\n that.triggerEventHandlers(target[key])\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.groupId ? `&foreignUserGroupId=${this.config.groupId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n this.getGlobalState().previousFlows.set(\n flowData.slug,\n cloneFlow(this.flows[this.flows.length - 1])\n )\n })\n }\n }\n\n private async triggerEventHandlers(previousUserFlowState: UserFlowState) {\n if (previousUserFlowState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousUserFlowState.flowId) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n }\n}\n"],"mappings":";kjBAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,UAAAE,EAAA,YAAAC,IAAA,eAAAC,GAAAJ,ICAO,IAAMK,EAAiB,QCC9B,IAAAC,EAAkB,6BAClBC,EAA6B,gBCiBtB,IAAIC,EAAyD,CAAC,EAE9D,SAASC,EAAkBC,EAAuC,CACvE,MAAO,GAAGA,EAAe,gBAAgBA,EAAe,UAAUA,EAAe,QAAU,MACzFA,EAAe,SAAW,IAE9B,CCrBO,IAAMC,EAAN,KAAgB,CAQrB,YAAYC,EAAuB,CAPnC,KAAO,OAAwB,CAC7B,OAAQ,GACR,OAAQ,oCACR,OAAQC,EAAgB,EACxB,aAAc,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,CACtD,EAGE,IAAMC,EAAiB,OAAO,YAAY,OAAO,QAAQF,CAAM,EAAE,OAAO,CAAC,CAACG,EAAGC,CAAC,IAAMA,GAAK,IAAI,CAAC,EAE9F,KAAK,OAAS,CACZ,GAAG,KAAK,OACR,GAAGF,CACL,CACF,CAEA,MAAa,MAAMG,EAAcC,EAA4B,CAC3D,OAAOC,EAAc,GAAG,KAAK,OAAO,SAASF,IAAQ,CACnD,GAAIC,GAAW,CAAC,EAChB,GAAGE,EAAW,KAAK,OAAO,MAAM,CAClC,CAAC,CACH,CAEU,gBAAqC,CAC7C,IAAMC,EAAiBC,EAAkB,KAAK,MAAM,EACpD,GAAI,CAACC,EAAmBF,CAAc,EACpC,MAAM,IAAI,MAAM,yBAAyB,EAE3C,OAAOE,EAAmBF,CAAc,CAC1C,CACF,ECrBO,IAAMG,EAAN,cAAmBC,CAAU,CAmDlC,YAAYC,EAAuBC,EAA0B,CAC3D,MAAMD,CAAM,EAZd,KAAO,UAAqB,GAM5B,KAAQ,eACN,IAAI,IAEN,KAAQ,kBAAoB,CAAC,EAI3B,KAAK,YAAcC,EACnB,KAAK,gBAAgBA,CAAW,CAClC,CAEQ,gBAAgBA,EAA0B,CAChD,IAAMC,EAAc,KAAK,MAAMD,EAAY,IAAI,EACzCE,EAAQD,EAAY,OAASA,EAAY,MAAQ,CAAC,EACxD,KAAK,GAAKD,EAAY,KACtB,KAAK,QAAUA,EACf,KAAK,gBAAkBC,EACvB,KAAK,MAAQ,KAAK,gBAAgB,MAClC,KAAK,SAAW,KAAK,gBAAgB,SAErC,IAAME,EAAgB,KAAK,iBAAiB,EAC5C,GAAI,CAACA,EAAe,CAClB,QAAQ,MAAM,QAAQ,KAAK,0CAA0C,EACrE,OAEF,KAAK,iBAAmBA,EAExB,KAAK,YAAcA,EAAc,WAAaC,EAC9C,KAAK,UAAYD,EAAc,WAAaE,EAC5C,KAAK,UAAYF,EAAc,WAAaG,EAC5C,IAAMC,EAAe,KAAK,aAAe,KAAK,UACxCC,EACJR,EAAY,gBAAkBG,EAAc,gBAAkB,GAChE,KAAK,UAAY,CAACI,GAAgB,CAACC,EACnC,IAAMC,EAAW,IAAI,IAErBP,EAAM,QAAQ,CAACQ,EAAMC,IAAU,CAC7B,IAAMC,EAAoBT,EAAc,WAAWO,EAAK,EAAE,EACpDG,EAAU,CACd,GAAGH,EACH,YAAaE,EAAkB,YAAcE,EAC7C,UAAWF,EAAkB,YAAcG,EAC3C,SAAUH,EAAkB,OAC5B,UAAWA,EAAkB,QAC7B,MAAOD,CACT,EAEAE,EAAQ,MAAQ,MAAOG,GAA8C,CACnE,IAAMC,EAAc,KAAK,MAAM,IAAIP,EAAK,EAAE,EAE1C,GAAIO,EAAY,WAAaA,EAAY,YACvC,OAGFA,EAAY,UAAY,GACxB,IAAMC,EAAOC,EAAM,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,EAChED,EAAK,WAAWD,EAAY,EAAE,EAAE,WAAaF,EAC7CG,EAAK,WAAaD,EAAY,GAC9B,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAIC,EAEhD,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQD,EAAY,GACpB,KAAMD,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYD,CACd,CAAC,CACH,CAAC,EAED,MAAM,KAAK,qBAAqB,EAEhC,IAAMK,EAAuB,KAAK,iBAAiB,EACnDH,EAAY,YACVG,EAAqB,WAAWH,EAAY,EAAE,EAAE,YAAcH,EAChEG,EAAY,UACVG,EAAqB,WAAWH,EAAY,EAAE,EAAE,YAAcF,CAClE,EAEAF,EAAQ,SAAW,MAAOG,GAA8C,CACtE,IAAMC,EAAc,KAAK,MAAM,IAAIP,EAAK,EAAE,EAE1C,GAAIO,EAAY,YACd,OAIF,IAAMI,EADyB,KAAK,0BAA0B,EAClB,GAAK,KAAK,MAAM,KAE5DJ,EAAY,YAAc,GAC1B,KAAK,UAAY,GACjB,IAAMC,EAAOC,EAAM,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,EAEhED,EAAK,WAAWD,EAAY,EAAE,EAAE,WAAaH,EAC7CI,EAAK,UAAYG,EAAajB,EAAiBC,EAE/C,IAAMiB,EAAa,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAEX,EAAQ,CAAC,EACtDW,IACFJ,EAAK,WAAaI,GAGhBD,GACF,KAAK,gCAAgC,EAGvC,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAIH,EAGhD,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQD,EAAY,GACpB,KAAMD,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYF,CACd,CAAC,CACH,CAAC,EAEGO,EACF,MAAM,KAAK,SAAS,EAEpB,MAAM,KAAK,qBAAqB,EAGlC,IAAMD,EAAuB,KAAK,iBAAiB,EACnDH,EAAY,YACVG,EAAqB,WAAWH,EAAY,EAAE,EAAE,YAAcH,EAChEG,EAAY,UACVG,EAAqB,WAAWH,EAAY,EAAE,EAAE,YAAcF,CAClE,EAEAF,EAAQ,cAAiBU,GAA8D,CACrF,IAAMC,EAAkBC,GAAe,CACrC,GAAIA,EAAK,KAAO,KAAK,GACnB,OAEF,IAAMR,EAAcQ,EAAK,MAAM,IAAIf,EAAK,EAAE,EACpCgB,EAAe,KAAK,eAAe,IAAIH,CAAO,GAGlDN,EAAY,eAAgBS,GAAA,YAAAA,EAAc,cAC1CT,EAAY,aAAcS,GAAA,YAAAA,EAAc,YACxCT,EAAY,YAAaS,GAAA,YAAAA,EAAc,WACvCT,EAAY,aAAcS,GAAA,YAAAA,EAAc,cAExCH,EAAQN,EAAaS,GAAgBP,EAAMF,CAAW,CAAC,EACvD,KAAK,eAAe,IAAIM,EAASJ,EAAMF,CAAW,CAAC,EAEvD,EACA,KAAK,eAAe,EAAE,iCAAiC,IAAIM,EAASC,CAAc,EAClF,KAAK,eAAe,EAAE,0BAA0B,KAAKA,CAAc,CACrE,EAEAX,EAAQ,yBACNU,GACG,CACH,IAAMC,EAAiB,KAAK,eAAe,EAAE,iCAAiC,IAAID,CAAO,EACrFC,IACF,KAAK,eAAe,EAAE,0BACpB,KAAK,eAAe,EAAE,0BAA0B,OAAQ,GAAM,IAAMA,CAAc,EAExF,EAEAf,EAAS,IAAIC,EAAK,GAAIG,CAAO,CAC/B,CAAC,EACD,KAAK,MAAQJ,EAET,OAAO,KAAK,KAAK,iBAAiB,EAAE,OAAS,GAC/C,KAAK,eAAe,KAAK,iBAAiB,CAE9C,CAKA,MAAa,MAAMO,EAA2C,CAC5D,GAAI,KAAK,WAAa,KAAK,YACzB,OAGF,KAAK,UAAY,GACjB,IAAME,EAAOC,EAAM,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,EAChED,EAAK,UAAYb,EACjB,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAIa,EAEhD,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMF,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYX,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,CACvC,CAKA,MAAa,SAASW,EAA2C,CAC3D,KAAK,cAGT,KAAK,gCAAgC,EAErC,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMA,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYZ,CACd,CAAC,CACH,CAAC,EAED,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,EACvC,CAEQ,iCAAkC,CACxC,KAAK,UAAY,GACjB,KAAK,YAAc,GACnB,IAAMc,EAAOC,EAAM,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,EAChED,EAAK,UAAYd,EACjB,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAIc,EAChD,KAAK,UAAY,EACnB,CAKA,MAAa,KAAKF,EAA2C,CAC3D,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMA,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYV,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,CACvC,CAKA,MAAa,SAAU,CACrB,KAAK,YAAc,GACnB,KAAK,YAAc,GACnB,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAI,KAChD,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,UACR,KAAM,CAAC,EACP,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYqB,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,CAClC,CAMO,eAAehB,EAAqC,CACzD,OAAO,KAAK,MAAM,IAAI,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAEA,CAAK,CAAC,CAC5D,CAKO,gBAA2B,CAKhC,IAAMiB,EAJa,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAE,KAC9CC,GAAQ,KAAK,MAAM,IAAIA,CAAG,EAAE,cAAgB,IAAS,KAAK,MAAM,IAAIA,CAAG,EAAE,WAAa,EACzF,GAEoC,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAE,CAAC,EACnE,OAAO,KAAK,MAAM,IAAID,CAAa,CACrC,CAKO,2BAAoC,CACzC,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,OAAQlB,GAASA,EAAK,WAAW,EAAE,MAC5E,CAKO,2BAAoC,CACzC,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,OAAQA,GAAS,CAACA,EAAK,QAAQ,EAAE,MAC1E,CAEO,cAAca,EAAmD,CACtE,IAAMC,EAAiB,CAACC,EAAYK,IAAuB,EAEtDL,EAAK,KAAO,KAAK,KACfA,EAAK,cAAgBK,EAAa,aACjCL,EAAK,YAAcK,EAAa,WAChCL,EAAK,YAAcK,EAAa,WAChCL,EAAK,YAAcK,EAAa,YACpC,KAAK,UAAUL,EAAK,KAAK,IAAM,KAAK,UAAUK,EAAa,KAAK,IAEhEP,EAAQE,EAAMK,CAAY,CAE9B,EACA,KAAK,eAAe,EAAE,iCAAiC,IAAIP,EAASC,CAAc,EAClF,KAAK,eAAe,EAAE,0BAA0B,KAAKA,CAAc,CACrE,CAEO,yBAAyBD,EAAmD,CACjF,IAAMC,EAAiB,KAAK,eAAe,EAAE,iCAAiC,IAAID,CAAO,EACrFC,IACF,KAAK,eAAe,EAAE,0BACpB,KAAK,eAAe,EAAE,0BAA0B,OAAQO,GAAMA,IAAMP,CAAc,EAExF,CAEO,eAAeQ,EAAgC,CAEpD,IAAMC,EAAoBC,GAAgB,CACxC,IAAMC,EAAUD,EAAI,MAAM,YAAY,EACtC,OAAIC,GACFA,EAAQ,QAASC,GAAU,CACzB,IAAMC,EAAWD,EAAM,QAAQ,KAAM,EAAE,EAAE,QAAQ,IAAK,EAAE,EACxDF,EAAMA,EAAI,QAAQE,EAAOJ,EAAUK,CAAQ,GAAK,EAAE,CACpD,CAAC,EAEIH,CACT,EAEA,KAAK,MAAQD,EAAiB,KAAK,OAAS,EAAE,EAC9C,KAAK,SAAWA,EAAiB,KAAK,UAAY,EAAE,EACpD,KAAK,MAAM,QAASvB,GAAS,CAE3B,OAAO,KAAKA,CAAI,EAAE,QAASmB,GAAQ,CAC7B,OAAOnB,EAAKmB,CAAG,GAAM,WAEvBnB,EAAKmB,CAAG,EAAII,EAAiBvB,EAAKmB,CAAG,CAAC,EAE1C,CAAC,CACH,CAAC,EAED,KAAK,kBAAoBG,CAC3B,CAEQ,kBAAkC,CAExC,OADuB,KAAK,eAAe,EAAE,eACvB,KAAK,EAAE,CAC/B,CAEA,MAAc,sBAAuB,CACnC,MAAM,KAAK,eAAe,EAAE,sBAAsB,CACpD,CACF,EH1aO,IAAMM,EAAiB,iBACjBC,EAAe,eACfC,EAAe,eACfC,EAAmB,mBACnBC,EAAiB,iBACjBC,EAAe,eAGtBC,GAAoB,wBACpBC,GAAsB,0BACtBC,EAAY,oBACZC,GAAe,SACfC,EAAmB,aACnBC,GAAmB,IACnBC,GAAoB,IACpBC,EAAuB,SAEtB,SAASC,EAAUC,EAAkB,CAC1C,IAAMC,EAAU,IAAIC,EAAKF,EAAK,OAAQA,EAAK,OAAO,EAClD,OAAAC,EAAQ,YAAcD,EAAK,YAC3BC,EAAQ,UAAYD,EAAK,UACzBC,EAAQ,UAAYD,EAAK,UACzBC,EAAQ,UAAYD,EAAK,UACzBC,EAAQ,MAAQD,EAAK,MACdC,CACT,CAEO,SAASE,EAASC,EAAW,CAClC,OAAO,KAAK,MAAM,KAAK,UAAUA,CAAG,CAAC,CACvC,CAEO,SAASC,EAAWC,EAAgB,CACzC,MAAO,CACL,QAAS,CACP,cAAe,UAAUA,IACzB,eAAgB,mBAChB,wBAAyBC,EACzB,yBAA0B,YAC5B,CACF,CACF,CAEA,SAASC,EAAgBC,EAAa,CACpC,OAAIC,EAAM,EACD,OAAO,aAAa,QAAQ,GAAGZ,IAAuBW,GAAK,EAE7D,IACT,CAEA,SAASE,EAAgBF,EAAaG,EAAe,CAC/CF,EAAM,GACR,OAAO,aAAa,QAAQ,GAAGZ,IAAuBW,IAAOG,CAAK,CAEtE,CAEA,SAASC,GAAeJ,EAAaG,EAAY,CAC/CE,EAAmBL,CAAG,EAAIG,CAC5B,CAEA,SAASG,GAAeN,EAAkB,CACxC,OAAOK,EAAmBL,CAAG,CAC/B,CAEO,SAASO,GAAa,CAC3B,OAAO,KAAKF,CAAkB,EAAE,QAASL,GAAQ,CAC3CA,EAAI,WAAWd,CAAgB,GACjC,OAAOmB,EAAmBL,CAAG,CAEjC,CAAC,CACH,CAEO,SAASQ,GAAuB,CACjCP,EAAM,GAER,OAAO,KAAK,OAAO,YAAY,EAAE,QAASD,GAAQ,CAC5CA,EAAI,WAAWX,CAAoB,GACrC,OAAO,aAAa,WAAWW,CAAG,CAEtC,CAAC,CAEL,CAEA,eAAsBS,EAAcC,EAAaC,EAAc,CAC7D,IAAMC,EAAgB9B,GAAoB4B,EACpCG,EAAkB9B,GAAsB2B,EAC9C,GAAIT,EAAM,GAAKU,GAAWA,EAAQ,MAAQA,EAAQ,SAAW,OAAQ,CACnE,IAAMG,EAAWf,EAAgBa,CAAa,EACxCG,EAAehB,EAAgBc,CAAe,EACpD,GAAIC,GAAYC,GAAgBA,GAAgBJ,EAAQ,KAAM,CAC5D,IAAMK,EAAe,IAAI,KAAKF,CAAQ,EAItC,GAHY,IAAI,KAAK,EACJ,QAAQ,EAAIE,EAAa,QAAQ,EAEvC5B,GACT,OAAO6B,EAAiB,EAG5Bf,EAAgBU,EAAe,IAAI,KAAK,EAAE,YAAY,CAAC,EACvDV,EAAgBW,EAAiBF,EAAQ,IAAI,EAC7CJ,EAAW,EAGb,IAAMW,GAAYP,GAAA,YAAAA,EAAS,UAAW,OAAS,EAACA,GAAA,MAAAA,EAAS,QACzD,GAAIO,EAAW,CACb,IAAMC,EAAiBb,GAAe,GAAGpB,IAAmBwB,GAAK,EACjE,GAAIS,GACU,IAAI,KAAK,EACJ,QAAQ,EAAIA,EAAe,UACjChC,GACT,OAAOgC,EAAe,SAK5B,IAAIC,EACJ,GAAI,CAEF,GADAA,KAAW,EAAAC,SAAMX,EAAKC,CAAO,EACzBO,EAAW,CACb,IAAMI,EAAkBF,EAAS,KAAMG,GAC9BA,EAAI,MAAM,EAAE,KAAK,CACzB,EACDnB,GAAe,GAAGlB,IAAmBwB,IAAO,CAC1C,SAAUY,EACV,UAAW,IAAI,KAAK,EAAE,QAAQ,CAChC,CAAC,EAGHF,EAAW,MAAMA,CACnB,OAASI,EAAP,CACA,OAAOP,EAAiBO,CAAK,CAC/B,CAEA,GAAI,CAACJ,EACH,OAAOH,EAAiB,4BAA4B,EAGtD,GAAIG,EAAS,QAAU,IACrB,OAAOH,EAAiBG,EAAS,UAAU,EAG7C,GAAI,CACF,IAAMK,EAAO,MAAML,EAAS,KAAK,EACjC,OAAIK,EAAK,MACAR,EAAiBQ,EAAK,KAAK,EAE7BA,CACT,OAASC,EAAP,CACA,OAAOT,EAAiBS,CAAC,CAC3B,CACF,CAEA,SAAST,EAAiBO,EAAa,CACrC,OAAIA,GACF,QAAQ,IAAI,yBAA0BA,CAAK,EAItC,CACL,KAAM,KAAO,CAAC,EAChB,CACF,CAEO,SAASG,GAAkB,CAChC,GAAI1B,EAAM,EAAG,CACX,IAAI2B,EAAU7B,EAAgBf,CAAS,EACvC,OAAK4C,IACHA,EAAU,GAAG3C,QAAe,EAAA4C,IAAO,IACnC3B,EAAgBlB,EAAW4C,CAAO,GAE7BA,EAEX,CASO,SAASE,GAAQ,CACtB,OAAO,OAAO,OAAW,GAC3B,CItLO,IAAMC,EAAN,cAAsBC,CAAU,CAIrC,YAAYC,EAAgBC,EAAwB,CAClD,MAAM,CACJ,OAAAD,EACA,GAAGC,CACL,CAAC,EAPH,KAAQ,MAAgB,CAAC,EASvB,KAAK,KAAK,KAAK,MAAM,EACjBC,EAAM,GACR,SAAS,iBAAiB,mBAAoB,SAAY,CACpD,SAAS,kBAAoB,YAC/B,MAAM,KAAK,aAAa,EACxB,MAAM,KAAK,sBAAsB,EAErC,CAAC,CAEL,CAEA,MAAc,KAAKD,EAAsC,CACvD,YAAK,OAAS,CACZ,GAAG,KAAK,OACR,GAAGA,CACL,EAEA,KAAK,aAAe,SAAY,CAC9B,MAAM,KAAK,sBAAsB,EACjC,MAAM,KAAK,aAAa,CAC1B,GAAG,EAEI,KAAK,WACd,CAEA,MAAa,SAASE,EAAgBC,EAAiD,CACrF,KAAK,OAAS,CAAE,OAAAD,CAAO,EACvB,MAAM,KAAK,aAAa,EACxB,MAAM,KAAK,MAAM,SAAU,CACzB,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,UAAW,KAAK,OAAO,OACvB,WAAAC,CACF,CAAC,CACH,CAAC,EACD,MAAM,KAAK,sBAAsB,CACnC,CAEA,MAAa,MAAMC,EAAwBD,EAAiD,CAC1F,MAAM,KAAK,aAAa,EACxB,KAAK,OAAO,QAAUC,EACtB,MAAM,KAAK,MAAM,cAAe,CAC9B,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,mBAAoB,KAAK,OAAO,QAChC,WAAAD,CACF,CAAC,CACH,CAAC,EACD,MAAM,KAAK,sBAAsB,CACnC,CAEA,MAAa,MAAME,EAAeF,EAAiD,CACjF,MAAM,KAAK,aAAa,EACxB,MAAM,KAAK,MAAM,SAAU,CACzB,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,mBAAoB,KAAK,OAAO,QAChC,MAAAE,EACA,WAAAF,CACF,CAAC,CACH,CAAC,CACH,CAEA,MAAa,QAAQG,EAAgB,CACnC,aAAM,KAAK,aAAa,EAEjB,KAAK,MAAM,KAAMC,GAASA,EAAK,IAAMD,CAAM,CACpD,CAEA,MAAa,UAAW,CACtB,aAAM,KAAK,aAAa,EACjB,KAAK,KACd,CAMA,MAAa,QAAS,CACpBE,EAAqB,EACrBC,EAAW,EACX,MAAM,KAAK,sBAAsB,EACjC,MAAM,KAAK,aAAa,EACxB,KAAK,YAAc,KACnB,MAAM,KAAK,KAAK,KAAK,MAAM,EAE3B,KAAK,MAAM,QAASF,GAAS,CAC3B,KAAK,eAAe,EAAE,0BAA0B,QAASG,GAAY,CACnE,IAAMC,EAAW,KAAK,eAAe,EAAE,cAAc,IAAIJ,EAAK,EAAE,EAChEG,EAAQH,EAAMI,CAAQ,EACtB,KAAK,eAAe,EAAE,cAAc,IAAIJ,EAAK,GAAIK,EAAUL,CAAI,CAAC,CAClE,CAAC,CACH,CAAC,CACH,CAEO,cAAcG,EAAoD,CACvE,KAAK,eAAe,EAAE,0BAA0B,KAAKA,CAAO,CAC9D,CAEO,yBAAyBA,EAAoD,CAClF,KAAK,eAAe,EAAE,0BACpB,KAAK,eAAe,EAAE,0BAA0B,OAAQG,GAAMA,IAAMH,CAAO,CAC/E,CAEA,MAAc,cAAe,CAC3B,OAAI,KAAK,cAAgB,KAChB,KAAK,YAEL,KAAK,KAAK,KAAK,MAAM,CAEhC,CAEA,MAAc,uBAAuC,CACnD,IAAMI,EAAiBC,EAAkB,KAAK,MAAM,EAEpD,GAAI,CAACC,EAAmBF,CAAc,EAAG,CACvC,IAAMG,EAAO,KAETC,EAAY,CACd,IAAK,SAAUC,EAAaC,EAAUC,EAAY,CAChD,OACEF,EAAOC,CAAG,GACVD,EAAOC,CAAG,EAAE,YACX,KAAK,UAAUD,EAAOC,CAAG,EAAE,SAAS,IAAM,KAAK,UAAUC,EAAM,SAAS,GACvE,KAAK,UAAUF,EAAOC,CAAG,EAAE,UAAU,IAAM,KAAK,UAAUC,EAAM,UAAU,GAC1E,KAAK,UAAUF,EAAOC,CAAG,EAAE,aAAa,IAAM,KAAK,UAAUC,EAAM,aAAa,IAElFJ,EAAK,qBAAqBE,EAAOC,CAAG,CAAC,EAGvCD,EAAOC,CAAG,EAAIC,EACP,EACT,CACF,EAEAL,EAAmBF,CAAc,EAAI,CACnC,sBAAuB,SAAY,CAAC,EACpC,eAAgB,IAAI,MAAM,CAAC,EAAGI,CAAS,EACvC,iCAAkC,IAAI,IACtC,iCAAkC,IAAI,IACtC,0BAA2B,CAAC,EAC5B,cAAe,IAAI,GACrB,EACAF,EAAmBF,CAAc,EAAE,sBAAwB,SAAY,CACrE,IAAMQ,EAAoB,MAAM,KAAK,MACnC,iCAAiC,KAAK,OAAO,SAC3C,KAAK,OAAO,QAAU,uBAAuB,KAAK,OAAO,UAAY,IAEzE,EACIA,GAAqBA,EAAkB,MACpBA,EAAkB,KACxB,QAASC,GAAkB,CACxCP,EAAmBF,CAAc,EAAE,eAAeS,EAAc,MAAM,EAAIA,CAC5E,CAAC,CAEL,EAGF,MAAMP,EAAmBF,CAAc,EAAE,sBAAsB,CACjE,CAEA,MAAc,cAAe,CAC3B,KAAK,MAAQ,CAAC,EACd,IAAMU,EAAc,MAAM,KAAK,MAAM,QAAQ,EACzCA,GAAeA,EAAY,MACbA,EAAY,KAClB,QAASC,GAAa,CAC9B,KAAK,MAAM,KAAK,IAAIC,EAAK,KAAK,OAAQD,CAAQ,CAAC,EAC/C,KAAK,eAAe,EAAE,cAAc,IAClCA,EAAS,KACTb,EAAU,KAAK,MAAM,KAAK,MAAM,OAAS,CAAC,CAAC,CAC7C,CACF,CAAC,CAEL,CAEA,MAAc,qBAAqBe,EAAsC,CACnEA,GACF,KAAK,MAAM,QAASpB,GAAS,CACvBA,EAAK,IAAMoB,EAAsB,QACnC,KAAK,eAAe,EAAE,0BAA0B,QAASjB,GAAY,CACnE,IAAMC,EAAW,KAAK,eAAe,EAAE,cAAc,IAAIJ,EAAK,EAAE,EAChEG,EAAQH,EAAMI,CAAQ,EACtB,KAAK,eAAe,EAAE,cAAc,IAAIJ,EAAK,GAAIK,EAAUL,CAAI,CAAC,CAClE,CAAC,CAEL,CAAC,CAEL,CACF","names":["src_exports","__export","Flow","Frigade","__toCommonJS","VERSION_NUMBER","import_cross_fetch","import_uuid","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","filteredConfig","_","v","path","options","gracefulFetch","getHeaders","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","hasCompleted","targetingShouldHideFlow","newSteps","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","handler","wrapperHandler","flow","previousStep","NOT_STARTED_FLOW","currentStepId","key","previousFlow","h","variables","replaceVariables","str","matches","match","variable","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","GET_CACHE_TTL_MS","POST_CACHE_TTL_MS","LOCAL_STORAGE_PREFIX","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","setGlobalState","frigadeGlobalState","getGlobalState","clearCache","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","isGetCall","cachedResponse","response","fetch","responsePromise","res","error","body","e","generateGuestId","guestId","uuidv4","isWeb","Frigade","Fetchable","apiKey","config","isWeb","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","previousUserFlowState"]}
package/dist/index.d.ts CHANGED
@@ -307,7 +307,11 @@ declare class Frigade extends Fetchable {
307
307
  track(event: string, properties?: Record<string, any>): Promise<void>;
308
308
  getFlow(flowId: string): Promise<Flow>;
309
309
  getFlows(): Promise<Flow[]>;
310
- reset(): Promise<void>;
310
+ /**
311
+ * Reload the current state of the flows by calling the Frigade API.
312
+ * This will trigger all event handlers.
313
+ */
314
+ reload(): Promise<void>;
311
315
  onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void): void;
312
316
  removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void): void;
313
317
  private initIfNeeded;
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- var W="0.2.7";import j from"cross-fetch";import{v4 as B}from"uuid";var c={};function D(e){return`${e.__instanceId}-${e.apiKey}:${e.userId??""}:${e.groupId??""}`}var F=class{constructor(o){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:$(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(o).filter(([s,a])=>a!=null));this.config={...this.config,...t}}async fetch(o,t){return J(`${this.config.apiUrl}${o}`,{...t??{},...M(this.config.apiKey)})}getGlobalState(){let o=D(this.config);if(!c[o])throw new Error("Frigade not initialized");return c[o]}};var w=class extends F{constructor(t,s){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.lastUsedVariables={};this.flowDataRaw=s,this.initFromRawData(s)}initFromRawData(t){let s=JSON.parse(t.data),a=s.steps??s.data??[];this.id=t.slug,this.rawData=t,this.configYmlAsJson=s,this.title=this.configYmlAsJson.title,this.subtitle=this.configYmlAsJson.subtitle;let i=this.getUserFlowState();if(!i){console.error(`Flow ${this.id} is not defined in the userFlowStates.`);return}this.userFlowStateRaw=i,this.isCompleted=i.flowState==O,this.isStarted=i.flowState==E,this.isSkipped=i.flowState==_;let r=this.isCompleted||this.isSkipped,d=t.targetingLogic&&i.shouldTrigger===!1;this.isVisible=!r&&!d;let T=new Map;a.forEach((f,R)=>{let I=i.stepStates[f.id],C={...f,isCompleted:I.actionType==m,isStarted:I.actionType==b,isHidden:I.hidden,isBlocked:I.blocked,order:R};C.start=async S=>{let n=this.steps.get(f.id);if(n.isStarted||n.isCompleted)return;n.isStarted=!0;let h=g(this.getGlobalState().userFlowStates[this.id]);h.stepStates[n.id].actionType=b,h.lastStepId=n.id,this.getGlobalState().userFlowStates[this.id]=h,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:n.id,data:S??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState();let p=this.getUserFlowState();n.isCompleted=p.stepStates[n.id].actionType==m,n.isStarted=p.stepStates[n.id].actionType==b},C.complete=async S=>{let n=this.steps.get(f.id);if(n.isCompleted)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size;n.isCompleted=!0,this.isStarted=!0;let l=g(this.getGlobalState().userFlowStates[this.id]);l.stepStates[n.id].actionType=m,l.flowState=p?O:E;let N=Array.from(this.steps.keys())[R+1];N&&(l.lastStepId=N),p&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=l,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:n.id,data:S??{},createdAt:new Date().toISOString(),actionType:m})}),p?await this.complete():await this.refreshUserFlowState();let x=this.getUserFlowState();n.isCompleted=x.stepStates[n.id].actionType==m,n.isStarted=x.stepStates[n.id].actionType==b},C.onStateChange=S=>{let n=h=>{if(h.id!==this.id)return;let p=h.steps.get(f.id),l=this.lastStepUpdate.get(S);(p.isCompleted!==(l==null?void 0:l.isCompleted)||p.isStarted!==(l==null?void 0:l.isStarted)||p.isHidden!==(l==null?void 0:l.isHidden)||p.isBlocked!==(l==null?void 0:l.isBlocked))&&(S(p,l??g(p)),this.lastStepUpdate.set(S,g(p)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(S,n),this.getGlobalState().onFlowStateChangeHandlers.push(n)},C.removeStateChangeHandler=S=>{let n=this.getGlobalState().onStepStateChangeHandlerWrappers.get(S);n&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(h=>h!==n))},T.set(f.id,C)}),this.steps=T,Object.keys(this.lastUsedVariables).length>0&&this.applyVariables(this.lastUsedVariables)}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let s=g(this.getGlobalState().userFlowStates[this.id]);s.flowState=E,this.getGlobalState().userFlowStates[this.id]=s,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:E})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:O})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=g(this.getGlobalState().userFlowStates[this.id]);t.flowState=O,this.getGlobalState().userFlowStates[this.id]=t,this.isVisible=!1}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:_})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,this.getGlobalState().userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:K})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let s=Array.from(this.steps.keys()).find(a=>this.steps.get(a).isCompleted===!1&&this.steps.get(a).isHidden===!1)??Array.from(this.steps.keys())[0];return this.steps.get(s)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>!t.isHidden).length}onStateChange(t){let s=(a,i)=>{(a.id===this.id&&(a.isCompleted!==i.isCompleted||a.isStarted!==i.isStarted||a.isSkipped!==i.isSkipped||a.isVisible!==i.isVisible)||JSON.stringify(a.steps)!==JSON.stringify(i.steps))&&t(a,i)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,s),this.getGlobalState().onFlowStateChangeHandlers.push(s)}removeStateChangeHandler(t){let s=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);s&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(a=>a!==s))}applyVariables(t){let s=a=>{let i=a.match(/\${(.*?)}/g);return i&&i.forEach(r=>{let d=r.replace("${","").replace("}","");a=a.replace(r,t[d]??"")}),a};this.title=s(this.title??""),this.subtitle=s(this.subtitle??""),this.steps.forEach(a=>{Object.keys(a).forEach(i=>{typeof a[i]=="string"&&(a[i]=s(a[i]))})}),this.lastUsedVariables=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var O="COMPLETED_FLOW",_="SKIPPED_FLOW",E="STARTED_FLOW",K="NOT_STARTED_FLOW",m="COMPLETED_STEP",b="STARTED_STEP",Y="frigade-last-call-at-",X="frigade-last-call-data-",V="frigade-guest-key",z="guest_",P="get-cache-",q=1e3,Q=1e3,G="fr-js-";function A(e){let o=new w(e.config,e.rawData);return o.isCompleted=e.isCompleted,o.isStarted=e.isStarted,o.isSkipped=e.isSkipped,o.isVisible=e.isVisible,o.steps=e.steps,o}function g(e){return JSON.parse(JSON.stringify(e))}function M(e){return{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","X-Frigade-SDK-Version":W,"X-Frigade-SDK-Platform":"Javascript"}}}function U(e){return u()?window.localStorage.getItem(`${G}${e}`):null}function v(e,o){u()&&window.localStorage.setItem(`${G}${e}`,o)}function Z(e,o){c[e]=o}function tt(e){return c[e]}function L(){Object.keys(c).forEach(e=>{e.startsWith(P)&&delete c[e]})}function k(){u()&&Object.keys(window.localStorage).forEach(e=>{e.startsWith(G)&&window.localStorage.removeItem(e)})}async function J(e,o){let t=Y+e,s=X+e;if(u()&&o&&o.body&&o.method==="POST"){let r=U(t),d=U(s);if(r&&d&&d==o.body){let T=new Date(r);if(new Date().getTime()-T.getTime()<Q)return y()}v(t,new Date().toISOString()),v(s,o.body),L()}let a=(o==null?void 0:o.method)==="GET"||!(o!=null&&o.method);if(a){let r=tt(`${P}${e}`);if(r&&new Date().getTime()-r.timestamp<q)return r.response}let i;try{if(i=j(e,o),a){let r=i.then(d=>d.clone().json());Z(`${P}${e}`,{response:r,timestamp:new Date().getTime()})}i=await i}catch(r){return y(r)}if(!i)return y("Received an empty response");if(i.status>=400)return y(i.statusText);try{let r=await i.json();return r.error?y(r.error):r}catch(r){return y(r)}}function y(e){return e&&console.log("Call to Frigade failed",e),{json:()=>({})}}function $(){if(u()){let e=U(V);return e||(e=`${z}${B()}`,v(V,e)),e}}function u(){return typeof window<"u"}var H=class extends F{constructor(t,s){super({apiKey:t,...s});this.flows=[];this.init(this.config),u()&&document.addEventListener("visibilitychange",async()=>{document.visibilityState==="visible"&&(await this.refreshFlows(),await this.refreshUserFlowStates())})}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,s){this.config={userId:t},await this.initIfNeeded(),await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:s})}),await this.refreshUserFlowStates()}async group(t,s){await this.initIfNeeded(),this.config.groupId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:s})}),await this.refreshUserFlowStates()}async track(t,s){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,event:t,properties:s})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(s=>s.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){k(),L(),this.initPromise=null,await this.init(this.config)}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}removeStateChangeHandler(t){this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(s=>s!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=D(this.config);if(!c[t]){let s=this,a={set:function(i,r,d){return i[r]&&i[r].flowState&&(JSON.stringify(i[r].flowState)!==JSON.stringify(d.flowState)||JSON.stringify(i[r].stepStates)!==JSON.stringify(d.stepStates)||JSON.stringify(i[r].shouldTrigger)!==JSON.stringify(d.shouldTrigger))&&s.triggerEventHandlers(i[r]),i[r]=d,!0}};c[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},a),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},c[t].refreshUserFlowStates=async()=>{let i=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.groupId?`&foreignUserGroupId=${this.config.groupId}`:""}`);i&&i.data&&i.data.forEach(d=>{c[t].userFlowStates[d.flowId]=d})}}await c[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(a=>{this.flows.push(new w(this.config,a)),this.getGlobalState().previousFlows.set(a.slug,A(this.flows[this.flows.length-1]))})}async triggerEventHandlers(t){t&&this.flows.forEach(s=>{s.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(a=>{let i=this.getGlobalState().previousFlows.get(s.id);a(s,i),this.getGlobalState().previousFlows.set(s.id,A(s))})})}};export{w as Flow,H as Frigade};
2
+ var W="0.2.8";import j from"cross-fetch";import{v4 as B}from"uuid";var c={};function D(s){return`${s.__instanceId}-${s.apiKey}:${s.userId??""}:${s.groupId??""}`}var F=class{constructor(o){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:$(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(o).filter(([e,a])=>a!=null));this.config={...this.config,...t}}async fetch(o,t){return J(`${this.config.apiUrl}${o}`,{...t??{},...M(this.config.apiKey)})}getGlobalState(){let o=D(this.config);if(!c[o])throw new Error("Frigade not initialized");return c[o]}};var w=class extends F{constructor(t,e){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.lastUsedVariables={};this.flowDataRaw=e,this.initFromRawData(e)}initFromRawData(t){let e=JSON.parse(t.data),a=e.steps??e.data??[];this.id=t.slug,this.rawData=t,this.configYmlAsJson=e,this.title=this.configYmlAsJson.title,this.subtitle=this.configYmlAsJson.subtitle;let i=this.getUserFlowState();if(!i){console.error(`Flow ${this.id} is not defined in the userFlowStates.`);return}this.userFlowStateRaw=i,this.isCompleted=i.flowState==O,this.isStarted=i.flowState==E,this.isSkipped=i.flowState==P;let r=this.isCompleted||this.isSkipped,d=t.targetingLogic&&i.shouldTrigger===!1;this.isVisible=!r&&!d;let T=new Map;a.forEach((f,_)=>{let I=i.stepStates[f.id],C={...f,isCompleted:I.actionType==m,isStarted:I.actionType==b,isHidden:I.hidden,isBlocked:I.blocked,order:_};C.start=async S=>{let n=this.steps.get(f.id);if(n.isStarted||n.isCompleted)return;n.isStarted=!0;let h=g(this.getGlobalState().userFlowStates[this.id]);h.stepStates[n.id].actionType=b,h.lastStepId=n.id,this.getGlobalState().userFlowStates[this.id]=h,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:n.id,data:S??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState();let p=this.getUserFlowState();n.isCompleted=p.stepStates[n.id].actionType==m,n.isStarted=p.stepStates[n.id].actionType==b},C.complete=async S=>{let n=this.steps.get(f.id);if(n.isCompleted)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size;n.isCompleted=!0,this.isStarted=!0;let l=g(this.getGlobalState().userFlowStates[this.id]);l.stepStates[n.id].actionType=m,l.flowState=p?O:E;let N=Array.from(this.steps.keys())[_+1];N&&(l.lastStepId=N),p&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=l,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:n.id,data:S??{},createdAt:new Date().toISOString(),actionType:m})}),p?await this.complete():await this.refreshUserFlowState();let x=this.getUserFlowState();n.isCompleted=x.stepStates[n.id].actionType==m,n.isStarted=x.stepStates[n.id].actionType==b},C.onStateChange=S=>{let n=h=>{if(h.id!==this.id)return;let p=h.steps.get(f.id),l=this.lastStepUpdate.get(S);(p.isCompleted!==(l==null?void 0:l.isCompleted)||p.isStarted!==(l==null?void 0:l.isStarted)||p.isHidden!==(l==null?void 0:l.isHidden)||p.isBlocked!==(l==null?void 0:l.isBlocked))&&(S(p,l??g(p)),this.lastStepUpdate.set(S,g(p)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(S,n),this.getGlobalState().onFlowStateChangeHandlers.push(n)},C.removeStateChangeHandler=S=>{let n=this.getGlobalState().onStepStateChangeHandlerWrappers.get(S);n&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(h=>h!==n))},T.set(f.id,C)}),this.steps=T,Object.keys(this.lastUsedVariables).length>0&&this.applyVariables(this.lastUsedVariables)}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e=g(this.getGlobalState().userFlowStates[this.id]);e.flowState=E,this.getGlobalState().userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:E})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:O})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=g(this.getGlobalState().userFlowStates[this.id]);t.flowState=O,this.getGlobalState().userFlowStates[this.id]=t,this.isVisible=!1}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:P})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,this.getGlobalState().userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:K})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let e=Array.from(this.steps.keys()).find(a=>this.steps.get(a).isCompleted===!1&&this.steps.get(a).isHidden===!1)??Array.from(this.steps.keys())[0];return this.steps.get(e)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>!t.isHidden).length}onStateChange(t){let e=(a,i)=>{(a.id===this.id&&(a.isCompleted!==i.isCompleted||a.isStarted!==i.isStarted||a.isSkipped!==i.isSkipped||a.isVisible!==i.isVisible)||JSON.stringify(a.steps)!==JSON.stringify(i.steps))&&t(a,i)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,e),this.getGlobalState().onFlowStateChangeHandlers.push(e)}removeStateChangeHandler(t){let e=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);e&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(a=>a!==e))}applyVariables(t){let e=a=>{let i=a.match(/\${(.*?)}/g);return i&&i.forEach(r=>{let d=r.replace("${","").replace("}","");a=a.replace(r,t[d]??"")}),a};this.title=e(this.title??""),this.subtitle=e(this.subtitle??""),this.steps.forEach(a=>{Object.keys(a).forEach(i=>{typeof a[i]=="string"&&(a[i]=e(a[i]))})}),this.lastUsedVariables=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var O="COMPLETED_FLOW",P="SKIPPED_FLOW",E="STARTED_FLOW",K="NOT_STARTED_FLOW",m="COMPLETED_STEP",b="STARTED_STEP",Y="frigade-last-call-at-",X="frigade-last-call-data-",V="frigade-guest-key",z="guest_",G="get-cache-",q=1e3,Q=1e3,A="fr-js-";function R(s){let o=new w(s.config,s.rawData);return o.isCompleted=s.isCompleted,o.isStarted=s.isStarted,o.isSkipped=s.isSkipped,o.isVisible=s.isVisible,o.steps=s.steps,o}function g(s){return JSON.parse(JSON.stringify(s))}function M(s){return{headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json","X-Frigade-SDK-Version":W,"X-Frigade-SDK-Platform":"Javascript"}}}function v(s){return u()?window.localStorage.getItem(`${A}${s}`):null}function U(s,o){u()&&window.localStorage.setItem(`${A}${s}`,o)}function Z(s,o){c[s]=o}function tt(s){return c[s]}function H(){Object.keys(c).forEach(s=>{s.startsWith(G)&&delete c[s]})}function k(){u()&&Object.keys(window.localStorage).forEach(s=>{s.startsWith(A)&&window.localStorage.removeItem(s)})}async function J(s,o){let t=Y+s,e=X+s;if(u()&&o&&o.body&&o.method==="POST"){let r=v(t),d=v(e);if(r&&d&&d==o.body){let T=new Date(r);if(new Date().getTime()-T.getTime()<Q)return y()}U(t,new Date().toISOString()),U(e,o.body),H()}let a=(o==null?void 0:o.method)==="GET"||!(o!=null&&o.method);if(a){let r=tt(`${G}${s}`);if(r&&new Date().getTime()-r.timestamp<q)return r.response}let i;try{if(i=j(s,o),a){let r=i.then(d=>d.clone().json());Z(`${G}${s}`,{response:r,timestamp:new Date().getTime()})}i=await i}catch(r){return y(r)}if(!i)return y("Received an empty response");if(i.status>=400)return y(i.statusText);try{let r=await i.json();return r.error?y(r.error):r}catch(r){return y(r)}}function y(s){return s&&console.log("Call to Frigade failed",s),{json:()=>({})}}function $(){if(u()){let s=v(V);return s||(s=`${z}${B()}`,U(V,s)),s}}function u(){return typeof window<"u"}var L=class extends F{constructor(t,e){super({apiKey:t,...e});this.flows=[];this.init(this.config),u()&&document.addEventListener("visibilitychange",async()=>{document.visibilityState==="visible"&&(await this.refreshFlows(),await this.refreshUserFlowStates())})}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,e){this.config={userId:t},await this.initIfNeeded(),await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),await this.refreshUserFlowStates()}async group(t,e){await this.initIfNeeded(),this.config.groupId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:e})}),await this.refreshUserFlowStates()}async track(t,e){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,event:t,properties:e})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reload(){k(),H(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let a=this.getGlobalState().previousFlows.get(t.id);e(t,a),this.getGlobalState().previousFlows.set(t.id,R(t))})})}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}removeStateChangeHandler(t){this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(e=>e!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=D(this.config);if(!c[t]){let e=this,a={set:function(i,r,d){return i[r]&&i[r].flowState&&(JSON.stringify(i[r].flowState)!==JSON.stringify(d.flowState)||JSON.stringify(i[r].stepStates)!==JSON.stringify(d.stepStates)||JSON.stringify(i[r].shouldTrigger)!==JSON.stringify(d.shouldTrigger))&&e.triggerEventHandlers(i[r]),i[r]=d,!0}};c[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},a),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},c[t].refreshUserFlowStates=async()=>{let i=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.groupId?`&foreignUserGroupId=${this.config.groupId}`:""}`);i&&i.data&&i.data.forEach(d=>{c[t].userFlowStates[d.flowId]=d})}}await c[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(a=>{this.flows.push(new w(this.config,a)),this.getGlobalState().previousFlows.set(a.slug,R(this.flows[this.flows.length-1]))})}async triggerEventHandlers(t){t&&this.flows.forEach(e=>{e.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(a=>{let i=this.getGlobalState().previousFlows.get(e.id);a(e,i),this.getGlobalState().previousFlows.set(e.id,R(e))})})}};export{w as Flow,L as Frigade};
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/Fetchable.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export const VERSION_NUMBER = '0.2.7'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { frigadeGlobalState } from './state'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst GET_CACHE_TTL_MS = 1000\nconst POST_CACHE_TTL_MS = 1000\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow(flow.config, flow.rawData)\n newFlow.isCompleted = flow.isCompleted\n newFlow.isStarted = flow.isStarted\n newFlow.isSkipped = flow.isSkipped\n newFlow.isVisible = flow.isVisible\n newFlow.steps = flow.steps\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n }\n}\n\nfunction setGlobalState(key: string, value: any) {\n frigadeGlobalState[key] = value\n}\n\nfunction getGlobalState(key: string): any {\n return frigadeGlobalState[key]\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (isWeb() && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < POST_CACHE_TTL_MS) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n clearCache()\n }\n\n const isGetCall = options?.method === 'GET' || !options?.method\n if (isGetCall) {\n const cachedResponse = getGlobalState(`${GET_CACHE_PREFIX}${url}`)\n if (cachedResponse) {\n const now = new Date()\n const diff = now.getTime() - cachedResponse.timestamp\n if (diff < GET_CACHE_TTL_MS) {\n return cachedResponse.response\n }\n }\n }\n\n let response\n try {\n response = fetch(url, options)\n if (isGetCall) {\n const responsePromise = response.then((res) => {\n return res.clone().json()\n })\n setGlobalState(`${GET_CACHE_PREFIX}${url}`, {\n response: responsePromise,\n timestamp: new Date().getTime(),\n })\n }\n\n response = await response\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n const body = await response.json()\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n\nexport function isWeb() {\n return typeof window !== 'undefined'\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { Flow } from '../core/flow'\nimport { FlowStep } from '../core/flow-step'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n onFlowStateChangeHandlerWrappers: Map<\n (flow: Flow, previousFlow: Flow) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onStepStateChangeHandlerWrappers: Map<\n (step: FlowStep, previousStep: FlowStep) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[]\n previousFlows: Map<string, Flow>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.groupId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade not initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public configYmlAsJson: any\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public rawData: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n /**\n * Whether the flow has been skipped or not\n */\n public isSkipped: boolean\n /**\n * Whether the flow is visible to the user based on the current user/group's state\n */\n public isVisible: boolean = false\n\n private readonly flowDataRaw: FlowDataRaw\n\n private userFlowStateRaw?: UserFlowState\n\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n private lastUsedVariables = {}\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.rawData = flowDataRaw\n this.configYmlAsJson = flowDataYml\n this.title = this.configYmlAsJson.title\n this.subtitle = this.configYmlAsJson.subtitle\n\n const userFlowState = this.getUserFlowState()\n if (!userFlowState) {\n console.error(`Flow ${this.id} is not defined in the userFlowStates.`)\n return\n }\n this.userFlowStateRaw = userFlowState\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.isSkipped = userFlowState.flowState == SKIPPED_FLOW\n const hasCompleted = this.isCompleted || this.isSkipped\n const targetingShouldHideFlow =\n flowDataRaw.targetingLogic && userFlowState.shouldTrigger === false\n this.isVisible = !hasCompleted && !targetingShouldHideFlow\n const newSteps = new Map<string, FlowStep>()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[currentStep.id].actionType = STARTED_STEP\n copy.lastStepId = currentStep.id\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n currentStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[currentStep.id].actionType = COMPLETED_STEP\n copy.flowState = isLastStep ? COMPLETED_FLOW : STARTED_FLOW\n\n const nextStepId = Array.from(this.steps.keys())[index + 1]\n if (nextStepId) {\n copy.lastStepId = nextStepId\n }\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n // if all steps are now completed, mark flow completed\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n if (isLastStep) {\n await this.complete()\n } else {\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const currentStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n currentStep.isCompleted !== previousStep?.isCompleted ||\n currentStep.isStarted !== previousStep?.isStarted ||\n currentStep.isHidden !== previousStep?.isHidden ||\n currentStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(currentStep, previousStep ?? clone(currentStep))\n this.lastStepUpdate.set(handler, clone(currentStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj)\n })\n this.steps = newSteps\n // Check if empty object\n if (Object.keys(this.lastUsedVariables).length > 0) {\n this.applyVariables(this.lastUsedVariables)\n }\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = STARTED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n private optimisticallyMarkFlowCompleted() {\n this.isStarted = true\n this.isCompleted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = COMPLETED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n this.isVisible = false\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n this.getGlobalState().userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false && this.steps.get(key).isHidden === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => !step.isHidden).length\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (\n (flow.id === this.id &&\n (flow.isCompleted !== previousFlow.isCompleted ||\n flow.isStarted !== previousFlow.isStarted ||\n flow.isSkipped !== previousFlow.isSkipped ||\n flow.isVisible !== previousFlow.isVisible)) ||\n JSON.stringify(flow.steps) !== JSON.stringify(previousFlow.steps)\n ) {\n handler(flow, previousFlow)\n }\n }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n public applyVariables(variables: Record<string, any>) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n str = str.replace(match, variables[variable] ?? '')\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n this.steps.forEach((step) => {\n // Iterate over every string field in the step and replace variables\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n }\n })\n })\n\n this.lastUsedVariables = variables\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { clearCache, cloneFlow, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshFlows()\n await this.refreshUserFlowStates()\n }\n })\n }\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { userId }\n await this.initIfNeeded()\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n clearCache()\n this.initPromise = null\n await this.init(this.config)\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n target[key] &&\n target[key].flowState &&\n (JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState) ||\n JSON.stringify(target[key].stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger))\n ) {\n that.triggerEventHandlers(target[key])\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.groupId ? `&foreignUserGroupId=${this.config.groupId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n this.getGlobalState().previousFlows.set(\n flowData.slug,\n cloneFlow(this.flows[this.flows.length - 1])\n )\n })\n }\n }\n\n private async triggerEventHandlers(previousUserFlowState: UserFlowState) {\n if (previousUserFlowState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousUserFlowState.flowId) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n }\n}\n"],"mappings":"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","names":["VERSION_NUMBER","fetch","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","filteredConfig","_","v","path","options","gracefulFetch","getHeaders","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","hasCompleted","targetingShouldHideFlow","newSteps","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","handler","wrapperHandler","flow","previousStep","NOT_STARTED_FLOW","currentStepId","key","previousFlow","h","variables","replaceVariables","str","matches","match","variable","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","GET_CACHE_TTL_MS","POST_CACHE_TTL_MS","LOCAL_STORAGE_PREFIX","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","setGlobalState","frigadeGlobalState","getGlobalState","clearCache","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","isGetCall","cachedResponse","response","fetch","responsePromise","res","error","body","e","generateGuestId","guestId","uuidv4","isWeb","Frigade","Fetchable","apiKey","config","isWeb","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","cloneFlow","previousUserFlowState","lastFlow"]}
1
+ {"version":3,"sources":["../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/Fetchable.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export const VERSION_NUMBER = '0.2.8'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { frigadeGlobalState } from './state'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst GET_CACHE_TTL_MS = 1000\nconst POST_CACHE_TTL_MS = 1000\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow(flow.config, flow.rawData)\n newFlow.isCompleted = flow.isCompleted\n newFlow.isStarted = flow.isStarted\n newFlow.isSkipped = flow.isSkipped\n newFlow.isVisible = flow.isVisible\n newFlow.steps = flow.steps\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n }\n}\n\nfunction setGlobalState(key: string, value: any) {\n frigadeGlobalState[key] = value\n}\n\nfunction getGlobalState(key: string): any {\n return frigadeGlobalState[key]\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (isWeb() && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < POST_CACHE_TTL_MS) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n clearCache()\n }\n\n const isGetCall = options?.method === 'GET' || !options?.method\n if (isGetCall) {\n const cachedResponse = getGlobalState(`${GET_CACHE_PREFIX}${url}`)\n if (cachedResponse) {\n const now = new Date()\n const diff = now.getTime() - cachedResponse.timestamp\n if (diff < GET_CACHE_TTL_MS) {\n return cachedResponse.response\n }\n }\n }\n\n let response\n try {\n response = fetch(url, options)\n if (isGetCall) {\n const responsePromise = response.then((res) => {\n return res.clone().json()\n })\n setGlobalState(`${GET_CACHE_PREFIX}${url}`, {\n response: responsePromise,\n timestamp: new Date().getTime(),\n })\n }\n\n response = await response\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n const body = await response.json()\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n\nexport function isWeb() {\n return typeof window !== 'undefined'\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { Flow } from '../core/flow'\nimport { FlowStep } from '../core/flow-step'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n onFlowStateChangeHandlerWrappers: Map<\n (flow: Flow, previousFlow: Flow) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onStepStateChangeHandlerWrappers: Map<\n (step: FlowStep, previousStep: FlowStep) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[]\n previousFlows: Map<string, Flow>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.groupId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade not initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public configYmlAsJson: any\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public rawData: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n /**\n * Whether the flow has been skipped or not\n */\n public isSkipped: boolean\n /**\n * Whether the flow is visible to the user based on the current user/group's state\n */\n public isVisible: boolean = false\n\n private readonly flowDataRaw: FlowDataRaw\n\n private userFlowStateRaw?: UserFlowState\n\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n private lastUsedVariables = {}\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.rawData = flowDataRaw\n this.configYmlAsJson = flowDataYml\n this.title = this.configYmlAsJson.title\n this.subtitle = this.configYmlAsJson.subtitle\n\n const userFlowState = this.getUserFlowState()\n if (!userFlowState) {\n console.error(`Flow ${this.id} is not defined in the userFlowStates.`)\n return\n }\n this.userFlowStateRaw = userFlowState\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.isSkipped = userFlowState.flowState == SKIPPED_FLOW\n const hasCompleted = this.isCompleted || this.isSkipped\n const targetingShouldHideFlow =\n flowDataRaw.targetingLogic && userFlowState.shouldTrigger === false\n this.isVisible = !hasCompleted && !targetingShouldHideFlow\n const newSteps = new Map<string, FlowStep>()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[currentStep.id].actionType = STARTED_STEP\n copy.lastStepId = currentStep.id\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n currentStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[currentStep.id].actionType = COMPLETED_STEP\n copy.flowState = isLastStep ? COMPLETED_FLOW : STARTED_FLOW\n\n const nextStepId = Array.from(this.steps.keys())[index + 1]\n if (nextStepId) {\n copy.lastStepId = nextStepId\n }\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n // if all steps are now completed, mark flow completed\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n if (isLastStep) {\n await this.complete()\n } else {\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const currentStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n currentStep.isCompleted !== previousStep?.isCompleted ||\n currentStep.isStarted !== previousStep?.isStarted ||\n currentStep.isHidden !== previousStep?.isHidden ||\n currentStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(currentStep, previousStep ?? clone(currentStep))\n this.lastStepUpdate.set(handler, clone(currentStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj)\n })\n this.steps = newSteps\n // Check if empty object\n if (Object.keys(this.lastUsedVariables).length > 0) {\n this.applyVariables(this.lastUsedVariables)\n }\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = STARTED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n private optimisticallyMarkFlowCompleted() {\n this.isStarted = true\n this.isCompleted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = COMPLETED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n this.isVisible = false\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n this.getGlobalState().userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false && this.steps.get(key).isHidden === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => !step.isHidden).length\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (\n (flow.id === this.id &&\n (flow.isCompleted !== previousFlow.isCompleted ||\n flow.isStarted !== previousFlow.isStarted ||\n flow.isSkipped !== previousFlow.isSkipped ||\n flow.isVisible !== previousFlow.isVisible)) ||\n JSON.stringify(flow.steps) !== JSON.stringify(previousFlow.steps)\n ) {\n handler(flow, previousFlow)\n }\n }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n public applyVariables(variables: Record<string, any>) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n str = str.replace(match, variables[variable] ?? '')\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n this.steps.forEach((step) => {\n // Iterate over every string field in the step and replace variables\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n }\n })\n })\n\n this.lastUsedVariables = variables\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { clearCache, cloneFlow, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshFlows()\n await this.refreshUserFlowStates()\n }\n })\n }\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { userId }\n await this.initIfNeeded()\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n /**\n * Reload the current state of the flows by calling the Frigade API.\n * This will trigger all event handlers.\n */\n public async reload() {\n resetAllLocalStorage()\n clearCache()\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n this.initPromise = null\n await this.init(this.config)\n // Trigger all event handlers\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n target[key] &&\n target[key].flowState &&\n (JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState) ||\n JSON.stringify(target[key].stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger))\n ) {\n that.triggerEventHandlers(target[key])\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.groupId ? `&foreignUserGroupId=${this.config.groupId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n this.getGlobalState().previousFlows.set(\n flowData.slug,\n cloneFlow(this.flows[this.flows.length - 1])\n )\n })\n }\n }\n\n private async triggerEventHandlers(previousUserFlowState: UserFlowState) {\n if (previousUserFlowState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousUserFlowState.flowId) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n }\n}\n"],"mappings":";AAAO,IAAMA,EAAiB,QCC9B,OAAOC,MAAW,cAClB,OAAS,MAAMC,MAAc,OCiBtB,IAAIC,EAAyD,CAAC,EAE9D,SAASC,EAAkBC,EAAuC,CACvE,MAAO,GAAGA,EAAe,gBAAgBA,EAAe,UAAUA,EAAe,QAAU,MACzFA,EAAe,SAAW,IAE9B,CCrBO,IAAMC,EAAN,KAAgB,CAQrB,YAAYC,EAAuB,CAPnC,KAAO,OAAwB,CAC7B,OAAQ,GACR,OAAQ,oCACR,OAAQC,EAAgB,EACxB,aAAc,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,CACtD,EAGE,IAAMC,EAAiB,OAAO,YAAY,OAAO,QAAQF,CAAM,EAAE,OAAO,CAAC,CAACG,EAAGC,CAAC,IAAMA,GAAK,IAAI,CAAC,EAE9F,KAAK,OAAS,CACZ,GAAG,KAAK,OACR,GAAGF,CACL,CACF,CAEA,MAAa,MAAMG,EAAcC,EAA4B,CAC3D,OAAOC,EAAc,GAAG,KAAK,OAAO,SAASF,IAAQ,CACnD,GAAIC,GAAW,CAAC,EAChB,GAAGE,EAAW,KAAK,OAAO,MAAM,CAClC,CAAC,CACH,CAEU,gBAAqC,CAC7C,IAAMC,EAAiBC,EAAkB,KAAK,MAAM,EACpD,GAAI,CAACC,EAAmBF,CAAc,EACpC,MAAM,IAAI,MAAM,yBAAyB,EAE3C,OAAOE,EAAmBF,CAAc,CAC1C,CACF,ECrBO,IAAMG,EAAN,cAAmBC,CAAU,CAmDlC,YAAYC,EAAuBC,EAA0B,CAC3D,MAAMD,CAAM,EAZd,KAAO,UAAqB,GAM5B,KAAQ,eACN,IAAI,IAEN,KAAQ,kBAAoB,CAAC,EAI3B,KAAK,YAAcC,EACnB,KAAK,gBAAgBA,CAAW,CAClC,CAEQ,gBAAgBA,EAA0B,CAChD,IAAMC,EAAc,KAAK,MAAMD,EAAY,IAAI,EACzCE,EAAQD,EAAY,OAASA,EAAY,MAAQ,CAAC,EACxD,KAAK,GAAKD,EAAY,KACtB,KAAK,QAAUA,EACf,KAAK,gBAAkBC,EACvB,KAAK,MAAQ,KAAK,gBAAgB,MAClC,KAAK,SAAW,KAAK,gBAAgB,SAErC,IAAME,EAAgB,KAAK,iBAAiB,EAC5C,GAAI,CAACA,EAAe,CAClB,QAAQ,MAAM,QAAQ,KAAK,0CAA0C,EACrE,OAEF,KAAK,iBAAmBA,EAExB,KAAK,YAAcA,EAAc,WAAaC,EAC9C,KAAK,UAAYD,EAAc,WAAaE,EAC5C,KAAK,UAAYF,EAAc,WAAaG,EAC5C,IAAMC,EAAe,KAAK,aAAe,KAAK,UACxCC,EACJR,EAAY,gBAAkBG,EAAc,gBAAkB,GAChE,KAAK,UAAY,CAACI,GAAgB,CAACC,EACnC,IAAMC,EAAW,IAAI,IAErBP,EAAM,QAAQ,CAACQ,EAAMC,IAAU,CAC7B,IAAMC,EAAoBT,EAAc,WAAWO,EAAK,EAAE,EACpDG,EAAU,CACd,GAAGH,EACH,YAAaE,EAAkB,YAAcE,EAC7C,UAAWF,EAAkB,YAAcG,EAC3C,SAAUH,EAAkB,OAC5B,UAAWA,EAAkB,QAC7B,MAAOD,CACT,EAEAE,EAAQ,MAAQ,MAAOG,GAA8C,CACnE,IAAMC,EAAc,KAAK,MAAM,IAAIP,EAAK,EAAE,EAE1C,GAAIO,EAAY,WAAaA,EAAY,YACvC,OAGFA,EAAY,UAAY,GACxB,IAAMC,EAAOC,EAAM,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,EAChED,EAAK,WAAWD,EAAY,EAAE,EAAE,WAAaF,EAC7CG,EAAK,WAAaD,EAAY,GAC9B,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAIC,EAEhD,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQD,EAAY,GACpB,KAAMD,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYD,CACd,CAAC,CACH,CAAC,EAED,MAAM,KAAK,qBAAqB,EAEhC,IAAMK,EAAuB,KAAK,iBAAiB,EACnDH,EAAY,YACVG,EAAqB,WAAWH,EAAY,EAAE,EAAE,YAAcH,EAChEG,EAAY,UACVG,EAAqB,WAAWH,EAAY,EAAE,EAAE,YAAcF,CAClE,EAEAF,EAAQ,SAAW,MAAOG,GAA8C,CACtE,IAAMC,EAAc,KAAK,MAAM,IAAIP,EAAK,EAAE,EAE1C,GAAIO,EAAY,YACd,OAIF,IAAMI,EADyB,KAAK,0BAA0B,EAClB,GAAK,KAAK,MAAM,KAE5DJ,EAAY,YAAc,GAC1B,KAAK,UAAY,GACjB,IAAMC,EAAOC,EAAM,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,EAEhED,EAAK,WAAWD,EAAY,EAAE,EAAE,WAAaH,EAC7CI,EAAK,UAAYG,EAAajB,EAAiBC,EAE/C,IAAMiB,EAAa,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAEX,EAAQ,CAAC,EACtDW,IACFJ,EAAK,WAAaI,GAGhBD,GACF,KAAK,gCAAgC,EAGvC,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAIH,EAGhD,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQD,EAAY,GACpB,KAAMD,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYF,CACd,CAAC,CACH,CAAC,EAEGO,EACF,MAAM,KAAK,SAAS,EAEpB,MAAM,KAAK,qBAAqB,EAGlC,IAAMD,EAAuB,KAAK,iBAAiB,EACnDH,EAAY,YACVG,EAAqB,WAAWH,EAAY,EAAE,EAAE,YAAcH,EAChEG,EAAY,UACVG,EAAqB,WAAWH,EAAY,EAAE,EAAE,YAAcF,CAClE,EAEAF,EAAQ,cAAiBU,GAA8D,CACrF,IAAMC,EAAkBC,GAAe,CACrC,GAAIA,EAAK,KAAO,KAAK,GACnB,OAEF,IAAMR,EAAcQ,EAAK,MAAM,IAAIf,EAAK,EAAE,EACpCgB,EAAe,KAAK,eAAe,IAAIH,CAAO,GAGlDN,EAAY,eAAgBS,GAAA,YAAAA,EAAc,cAC1CT,EAAY,aAAcS,GAAA,YAAAA,EAAc,YACxCT,EAAY,YAAaS,GAAA,YAAAA,EAAc,WACvCT,EAAY,aAAcS,GAAA,YAAAA,EAAc,cAExCH,EAAQN,EAAaS,GAAgBP,EAAMF,CAAW,CAAC,EACvD,KAAK,eAAe,IAAIM,EAASJ,EAAMF,CAAW,CAAC,EAEvD,EACA,KAAK,eAAe,EAAE,iCAAiC,IAAIM,EAASC,CAAc,EAClF,KAAK,eAAe,EAAE,0BAA0B,KAAKA,CAAc,CACrE,EAEAX,EAAQ,yBACNU,GACG,CACH,IAAMC,EAAiB,KAAK,eAAe,EAAE,iCAAiC,IAAID,CAAO,EACrFC,IACF,KAAK,eAAe,EAAE,0BACpB,KAAK,eAAe,EAAE,0BAA0B,OAAQ,GAAM,IAAMA,CAAc,EAExF,EAEAf,EAAS,IAAIC,EAAK,GAAIG,CAAO,CAC/B,CAAC,EACD,KAAK,MAAQJ,EAET,OAAO,KAAK,KAAK,iBAAiB,EAAE,OAAS,GAC/C,KAAK,eAAe,KAAK,iBAAiB,CAE9C,CAKA,MAAa,MAAMO,EAA2C,CAC5D,GAAI,KAAK,WAAa,KAAK,YACzB,OAGF,KAAK,UAAY,GACjB,IAAME,EAAOC,EAAM,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,EAChED,EAAK,UAAYb,EACjB,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAIa,EAEhD,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMF,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYX,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,CACvC,CAKA,MAAa,SAASW,EAA2C,CAC3D,KAAK,cAGT,KAAK,gCAAgC,EAErC,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMA,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYZ,CACd,CAAC,CACH,CAAC,EAED,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,EACvC,CAEQ,iCAAkC,CACxC,KAAK,UAAY,GACjB,KAAK,YAAc,GACnB,IAAMc,EAAOC,EAAM,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,EAChED,EAAK,UAAYd,EACjB,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAIc,EAChD,KAAK,UAAY,EACnB,CAKA,MAAa,KAAKF,EAA2C,CAC3D,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMA,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYV,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,CACvC,CAKA,MAAa,SAAU,CACrB,KAAK,YAAc,GACnB,KAAK,YAAc,GACnB,KAAK,eAAe,EAAE,eAAe,KAAK,EAAE,EAAI,KAChD,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,UACR,KAAM,CAAC,EACP,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYqB,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,CAClC,CAMO,eAAehB,EAAqC,CACzD,OAAO,KAAK,MAAM,IAAI,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAEA,CAAK,CAAC,CAC5D,CAKO,gBAA2B,CAKhC,IAAMiB,EAJa,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAE,KAC9CC,GAAQ,KAAK,MAAM,IAAIA,CAAG,EAAE,cAAgB,IAAS,KAAK,MAAM,IAAIA,CAAG,EAAE,WAAa,EACzF,GAEoC,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAE,CAAC,EACnE,OAAO,KAAK,MAAM,IAAID,CAAa,CACrC,CAKO,2BAAoC,CACzC,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,OAAQlB,GAASA,EAAK,WAAW,EAAE,MAC5E,CAKO,2BAAoC,CACzC,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,OAAQA,GAAS,CAACA,EAAK,QAAQ,EAAE,MAC1E,CAEO,cAAca,EAAmD,CACtE,IAAMC,EAAiB,CAACC,EAAYK,IAAuB,EAEtDL,EAAK,KAAO,KAAK,KACfA,EAAK,cAAgBK,EAAa,aACjCL,EAAK,YAAcK,EAAa,WAChCL,EAAK,YAAcK,EAAa,WAChCL,EAAK,YAAcK,EAAa,YACpC,KAAK,UAAUL,EAAK,KAAK,IAAM,KAAK,UAAUK,EAAa,KAAK,IAEhEP,EAAQE,EAAMK,CAAY,CAE9B,EACA,KAAK,eAAe,EAAE,iCAAiC,IAAIP,EAASC,CAAc,EAClF,KAAK,eAAe,EAAE,0BAA0B,KAAKA,CAAc,CACrE,CAEO,yBAAyBD,EAAmD,CACjF,IAAMC,EAAiB,KAAK,eAAe,EAAE,iCAAiC,IAAID,CAAO,EACrFC,IACF,KAAK,eAAe,EAAE,0BACpB,KAAK,eAAe,EAAE,0BAA0B,OAAQO,GAAMA,IAAMP,CAAc,EAExF,CAEO,eAAeQ,EAAgC,CAEpD,IAAMC,EAAoBC,GAAgB,CACxC,IAAMC,EAAUD,EAAI,MAAM,YAAY,EACtC,OAAIC,GACFA,EAAQ,QAASC,GAAU,CACzB,IAAMC,EAAWD,EAAM,QAAQ,KAAM,EAAE,EAAE,QAAQ,IAAK,EAAE,EACxDF,EAAMA,EAAI,QAAQE,EAAOJ,EAAUK,CAAQ,GAAK,EAAE,CACpD,CAAC,EAEIH,CACT,EAEA,KAAK,MAAQD,EAAiB,KAAK,OAAS,EAAE,EAC9C,KAAK,SAAWA,EAAiB,KAAK,UAAY,EAAE,EACpD,KAAK,MAAM,QAASvB,GAAS,CAE3B,OAAO,KAAKA,CAAI,EAAE,QAASmB,GAAQ,CAC7B,OAAOnB,EAAKmB,CAAG,GAAM,WAEvBnB,EAAKmB,CAAG,EAAII,EAAiBvB,EAAKmB,CAAG,CAAC,EAE1C,CAAC,CACH,CAAC,EAED,KAAK,kBAAoBG,CAC3B,CAEQ,kBAAkC,CAExC,OADuB,KAAK,eAAe,EAAE,eACvB,KAAK,EAAE,CAC/B,CAEA,MAAc,sBAAuB,CACnC,MAAM,KAAK,eAAe,EAAE,sBAAsB,CACpD,CACF,EH1aO,IAAMM,EAAiB,iBACjBC,EAAe,eACfC,EAAe,eACfC,EAAmB,mBACnBC,EAAiB,iBACjBC,EAAe,eAGtBC,EAAoB,wBACpBC,EAAsB,0BACtBC,EAAY,oBACZC,EAAe,SACfC,EAAmB,aACnBC,EAAmB,IACnBC,EAAoB,IACpBC,EAAuB,SAEtB,SAASC,EAAUC,EAAkB,CAC1C,IAAMC,EAAU,IAAIC,EAAKF,EAAK,OAAQA,EAAK,OAAO,EAClD,OAAAC,EAAQ,YAAcD,EAAK,YAC3BC,EAAQ,UAAYD,EAAK,UACzBC,EAAQ,UAAYD,EAAK,UACzBC,EAAQ,UAAYD,EAAK,UACzBC,EAAQ,MAAQD,EAAK,MACdC,CACT,CAEO,SAASE,EAASC,EAAW,CAClC,OAAO,KAAK,MAAM,KAAK,UAAUA,CAAG,CAAC,CACvC,CAEO,SAASC,EAAWC,EAAgB,CACzC,MAAO,CACL,QAAS,CACP,cAAe,UAAUA,IACzB,eAAgB,mBAChB,wBAAyBC,EACzB,yBAA0B,YAC5B,CACF,CACF,CAEA,SAASC,EAAgBC,EAAa,CACpC,OAAIC,EAAM,EACD,OAAO,aAAa,QAAQ,GAAGZ,IAAuBW,GAAK,EAE7D,IACT,CAEA,SAASE,EAAgBF,EAAaG,EAAe,CAC/CF,EAAM,GACR,OAAO,aAAa,QAAQ,GAAGZ,IAAuBW,IAAOG,CAAK,CAEtE,CAEA,SAASC,EAAeJ,EAAaG,EAAY,CAC/CE,EAAmBL,CAAG,EAAIG,CAC5B,CAEA,SAASG,GAAeN,EAAkB,CACxC,OAAOK,EAAmBL,CAAG,CAC/B,CAEO,SAASO,GAAa,CAC3B,OAAO,KAAKF,CAAkB,EAAE,QAASL,GAAQ,CAC3CA,EAAI,WAAWd,CAAgB,GACjC,OAAOmB,EAAmBL,CAAG,CAEjC,CAAC,CACH,CAEO,SAASQ,GAAuB,CACjCP,EAAM,GAER,OAAO,KAAK,OAAO,YAAY,EAAE,QAASD,GAAQ,CAC5CA,EAAI,WAAWX,CAAoB,GACrC,OAAO,aAAa,WAAWW,CAAG,CAEtC,CAAC,CAEL,CAEA,eAAsBS,EAAcC,EAAaC,EAAc,CAC7D,IAAMC,EAAgB9B,EAAoB4B,EACpCG,EAAkB9B,EAAsB2B,EAC9C,GAAIT,EAAM,GAAKU,GAAWA,EAAQ,MAAQA,EAAQ,SAAW,OAAQ,CACnE,IAAMG,EAAWf,EAAgBa,CAAa,EACxCG,EAAehB,EAAgBc,CAAe,EACpD,GAAIC,GAAYC,GAAgBA,GAAgBJ,EAAQ,KAAM,CAC5D,IAAMK,EAAe,IAAI,KAAKF,CAAQ,EAItC,GAHY,IAAI,KAAK,EACJ,QAAQ,EAAIE,EAAa,QAAQ,EAEvC5B,EACT,OAAO6B,EAAiB,EAG5Bf,EAAgBU,EAAe,IAAI,KAAK,EAAE,YAAY,CAAC,EACvDV,EAAgBW,EAAiBF,EAAQ,IAAI,EAC7CJ,EAAW,EAGb,IAAMW,GAAYP,GAAA,YAAAA,EAAS,UAAW,OAAS,EAACA,GAAA,MAAAA,EAAS,QACzD,GAAIO,EAAW,CACb,IAAMC,EAAiBb,GAAe,GAAGpB,IAAmBwB,GAAK,EACjE,GAAIS,GACU,IAAI,KAAK,EACJ,QAAQ,EAAIA,EAAe,UACjChC,EACT,OAAOgC,EAAe,SAK5B,IAAIC,EACJ,GAAI,CAEF,GADAA,EAAWC,EAAMX,EAAKC,CAAO,EACzBO,EAAW,CACb,IAAMI,EAAkBF,EAAS,KAAMG,GAC9BA,EAAI,MAAM,EAAE,KAAK,CACzB,EACDnB,EAAe,GAAGlB,IAAmBwB,IAAO,CAC1C,SAAUY,EACV,UAAW,IAAI,KAAK,EAAE,QAAQ,CAChC,CAAC,EAGHF,EAAW,MAAMA,CACnB,OAASI,EAAP,CACA,OAAOP,EAAiBO,CAAK,CAC/B,CAEA,GAAI,CAACJ,EACH,OAAOH,EAAiB,4BAA4B,EAGtD,GAAIG,EAAS,QAAU,IACrB,OAAOH,EAAiBG,EAAS,UAAU,EAG7C,GAAI,CACF,IAAMK,EAAO,MAAML,EAAS,KAAK,EACjC,OAAIK,EAAK,MACAR,EAAiBQ,EAAK,KAAK,EAE7BA,CACT,OAASC,EAAP,CACA,OAAOT,EAAiBS,CAAC,CAC3B,CACF,CAEA,SAAST,EAAiBO,EAAa,CACrC,OAAIA,GACF,QAAQ,IAAI,yBAA0BA,CAAK,EAItC,CACL,KAAM,KAAO,CAAC,EAChB,CACF,CAEO,SAASG,GAAkB,CAChC,GAAI1B,EAAM,EAAG,CACX,IAAI2B,EAAU7B,EAAgBf,CAAS,EACvC,OAAK4C,IACHA,EAAU,GAAG3C,IAAe4C,EAAO,IACnC3B,EAAgBlB,EAAW4C,CAAO,GAE7BA,EAEX,CASO,SAASE,GAAQ,CACtB,OAAO,OAAO,OAAW,GAC3B,CItLO,IAAMC,EAAN,cAAsBC,CAAU,CAIrC,YAAYC,EAAgBC,EAAwB,CAClD,MAAM,CACJ,OAAAD,EACA,GAAGC,CACL,CAAC,EAPH,KAAQ,MAAgB,CAAC,EASvB,KAAK,KAAK,KAAK,MAAM,EACjBC,EAAM,GACR,SAAS,iBAAiB,mBAAoB,SAAY,CACpD,SAAS,kBAAoB,YAC/B,MAAM,KAAK,aAAa,EACxB,MAAM,KAAK,sBAAsB,EAErC,CAAC,CAEL,CAEA,MAAc,KAAKD,EAAsC,CACvD,YAAK,OAAS,CACZ,GAAG,KAAK,OACR,GAAGA,CACL,EAEA,KAAK,aAAe,SAAY,CAC9B,MAAM,KAAK,sBAAsB,EACjC,MAAM,KAAK,aAAa,CAC1B,GAAG,EAEI,KAAK,WACd,CAEA,MAAa,SAASE,EAAgBC,EAAiD,CACrF,KAAK,OAAS,CAAE,OAAAD,CAAO,EACvB,MAAM,KAAK,aAAa,EACxB,MAAM,KAAK,MAAM,SAAU,CACzB,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,UAAW,KAAK,OAAO,OACvB,WAAAC,CACF,CAAC,CACH,CAAC,EACD,MAAM,KAAK,sBAAsB,CACnC,CAEA,MAAa,MAAMC,EAAwBD,EAAiD,CAC1F,MAAM,KAAK,aAAa,EACxB,KAAK,OAAO,QAAUC,EACtB,MAAM,KAAK,MAAM,cAAe,CAC9B,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,mBAAoB,KAAK,OAAO,QAChC,WAAAD,CACF,CAAC,CACH,CAAC,EACD,MAAM,KAAK,sBAAsB,CACnC,CAEA,MAAa,MAAME,EAAeF,EAAiD,CACjF,MAAM,KAAK,aAAa,EACxB,MAAM,KAAK,MAAM,SAAU,CACzB,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,mBAAoB,KAAK,OAAO,QAChC,MAAAE,EACA,WAAAF,CACF,CAAC,CACH,CAAC,CACH,CAEA,MAAa,QAAQG,EAAgB,CACnC,aAAM,KAAK,aAAa,EAEjB,KAAK,MAAM,KAAMC,GAASA,EAAK,IAAMD,CAAM,CACpD,CAEA,MAAa,UAAW,CACtB,aAAM,KAAK,aAAa,EACjB,KAAK,KACd,CAMA,MAAa,QAAS,CACpBE,EAAqB,EACrBC,EAAW,EACX,MAAM,KAAK,sBAAsB,EACjC,MAAM,KAAK,aAAa,EACxB,KAAK,YAAc,KACnB,MAAM,KAAK,KAAK,KAAK,MAAM,EAE3B,KAAK,MAAM,QAASF,GAAS,CAC3B,KAAK,eAAe,EAAE,0BAA0B,QAASG,GAAY,CACnE,IAAMC,EAAW,KAAK,eAAe,EAAE,cAAc,IAAIJ,EAAK,EAAE,EAChEG,EAAQH,EAAMI,CAAQ,EACtB,KAAK,eAAe,EAAE,cAAc,IAAIJ,EAAK,GAAIK,EAAUL,CAAI,CAAC,CAClE,CAAC,CACH,CAAC,CACH,CAEO,cAAcG,EAAoD,CACvE,KAAK,eAAe,EAAE,0BAA0B,KAAKA,CAAO,CAC9D,CAEO,yBAAyBA,EAAoD,CAClF,KAAK,eAAe,EAAE,0BACpB,KAAK,eAAe,EAAE,0BAA0B,OAAQG,GAAMA,IAAMH,CAAO,CAC/E,CAEA,MAAc,cAAe,CAC3B,OAAI,KAAK,cAAgB,KAChB,KAAK,YAEL,KAAK,KAAK,KAAK,MAAM,CAEhC,CAEA,MAAc,uBAAuC,CACnD,IAAMI,EAAiBC,EAAkB,KAAK,MAAM,EAEpD,GAAI,CAACC,EAAmBF,CAAc,EAAG,CACvC,IAAMG,EAAO,KAETC,EAAY,CACd,IAAK,SAAUC,EAAaC,EAAUC,EAAY,CAChD,OACEF,EAAOC,CAAG,GACVD,EAAOC,CAAG,EAAE,YACX,KAAK,UAAUD,EAAOC,CAAG,EAAE,SAAS,IAAM,KAAK,UAAUC,EAAM,SAAS,GACvE,KAAK,UAAUF,EAAOC,CAAG,EAAE,UAAU,IAAM,KAAK,UAAUC,EAAM,UAAU,GAC1E,KAAK,UAAUF,EAAOC,CAAG,EAAE,aAAa,IAAM,KAAK,UAAUC,EAAM,aAAa,IAElFJ,EAAK,qBAAqBE,EAAOC,CAAG,CAAC,EAGvCD,EAAOC,CAAG,EAAIC,EACP,EACT,CACF,EAEAL,EAAmBF,CAAc,EAAI,CACnC,sBAAuB,SAAY,CAAC,EACpC,eAAgB,IAAI,MAAM,CAAC,EAAGI,CAAS,EACvC,iCAAkC,IAAI,IACtC,iCAAkC,IAAI,IACtC,0BAA2B,CAAC,EAC5B,cAAe,IAAI,GACrB,EACAF,EAAmBF,CAAc,EAAE,sBAAwB,SAAY,CACrE,IAAMQ,EAAoB,MAAM,KAAK,MACnC,iCAAiC,KAAK,OAAO,SAC3C,KAAK,OAAO,QAAU,uBAAuB,KAAK,OAAO,UAAY,IAEzE,EACIA,GAAqBA,EAAkB,MACpBA,EAAkB,KACxB,QAASC,GAAkB,CACxCP,EAAmBF,CAAc,EAAE,eAAeS,EAAc,MAAM,EAAIA,CAC5E,CAAC,CAEL,EAGF,MAAMP,EAAmBF,CAAc,EAAE,sBAAsB,CACjE,CAEA,MAAc,cAAe,CAC3B,KAAK,MAAQ,CAAC,EACd,IAAMU,EAAc,MAAM,KAAK,MAAM,QAAQ,EACzCA,GAAeA,EAAY,MACbA,EAAY,KAClB,QAASC,GAAa,CAC9B,KAAK,MAAM,KAAK,IAAIC,EAAK,KAAK,OAAQD,CAAQ,CAAC,EAC/C,KAAK,eAAe,EAAE,cAAc,IAClCA,EAAS,KACTb,EAAU,KAAK,MAAM,KAAK,MAAM,OAAS,CAAC,CAAC,CAC7C,CACF,CAAC,CAEL,CAEA,MAAc,qBAAqBe,EAAsC,CACnEA,GACF,KAAK,MAAM,QAASpB,GAAS,CACvBA,EAAK,IAAMoB,EAAsB,QACnC,KAAK,eAAe,EAAE,0BAA0B,QAASjB,GAAY,CACnE,IAAMC,EAAW,KAAK,eAAe,EAAE,cAAc,IAAIJ,EAAK,EAAE,EAChEG,EAAQH,EAAMI,CAAQ,EACtB,KAAK,eAAe,EAAE,cAAc,IAAIJ,EAAK,GAAIK,EAAUL,CAAI,CAAC,CAClE,CAAC,CAEL,CAAC,CAEL,CACF","names":["VERSION_NUMBER","fetch","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","filteredConfig","_","v","path","options","gracefulFetch","getHeaders","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","hasCompleted","targetingShouldHideFlow","newSteps","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","handler","wrapperHandler","flow","previousStep","NOT_STARTED_FLOW","currentStepId","key","previousFlow","h","variables","replaceVariables","str","matches","match","variable","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","GET_CACHE_TTL_MS","POST_CACHE_TTL_MS","LOCAL_STORAGE_PREFIX","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","setGlobalState","frigadeGlobalState","getGlobalState","clearCache","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","isGetCall","cachedResponse","response","fetch","responsePromise","res","error","body","e","generateGuestId","guestId","uuidv4","isWeb","Frigade","Fetchable","apiKey","config","isWeb","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","previousUserFlowState"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frigade/js",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "The official Javascript SDK for Frigade.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",