@frigade/js 0.2.24 → 0.2.25

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 Q=Object.create;var U=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var et=Object.getPrototypeOf,it=Object.prototype.hasOwnProperty;var st=(s,a)=>{for(var t in a)U(s,t,{get:a[t],enumerable:!0})},V=(s,a,t,e)=>{if(a&&typeof a=="object"||typeof a=="function")for(let i of tt(a))!it.call(s,i)&&i!==t&&U(s,i,{get:()=>a[i],enumerable:!(e=Z(a,i))||e.enumerable});return s};var ot=(s,a,t)=>(t=s!=null?Q(et(s)):{},V(a||!s||!s.__esModule?U(t,"default",{value:s,enumerable:!0}):t,s)),at=s=>V(U({},"__esModule",{value:!0}),s);var ct={};st(ct,{Flow:()=>w,Frigade:()=>P});module.exports=at(ct);var k="0.2.20";var X=ot(require("cross-fetch"),1),z=require("uuid");var p={};function R(s){return`${s.__instanceId}-${s.apiKey}:${s.userId??""}:${s.groupId??""}`}var E=class{constructor(a){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:B(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(a).filter(([e,i])=>i!=null));this.config={...this.config,...t}}async fetch(a,t){return this.config.__readOnly?S():$(`${this.config.apiUrl}${a}`,{...t??{},...K(this.config.apiKey)})}getGlobalState(){let a=R(this.config);if(!p[a])throw new Error("Frigade not initialized");return p[a]}};var w=class extends E{constructor(t,e){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.lastUsedVariables={};this.flowDataRaw=e,this.initFromRawData(e)}reload(){this.initFromRawData(this.flowDataRaw)}initFromRawData(t){let e=JSON.parse(t.data),i=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 o=this.getUserFlowState();if(!o)return;this.userFlowStateRaw=o,this.isCompleted=o.flowState==D,this.isStarted=o.flowState==A,this.isSkipped=o.flowState==G;let c=this.isCompleted||this.isSkipped,n=t.targetingLogic&&o.shouldTrigger===!1;this.isVisible=!c&&!n,this.flowDataRaw.active===!1&&(this.isVisible=!1);let y=new Map;i.forEach((f,T)=>{let I=o.stepStates[f.id],C={...f,isCompleted:I.actionType==b,isStarted:I.actionType==u,isHidden:I.hidden,isBlocked:I.blocked,lastActionAt:I.lastActionAt?new Date(I.lastActionAt):void 0,order:T};C.start=async l=>{let r=this.steps.get(f.id);if(this.getCurrentStep().id===r.id&&r.isStarted)return;r.isStarted=!0;let g=F(this.getGlobalState().userFlowStates[this.id]);g.stepStates[r.id].actionType=u,g.stepStates[r.id].lastActionAt=new Date().toISOString(),g.lastStepId=r.id,this.getGlobalState().userFlowStates[this.id]=g,r.isCompleted||(await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:r.id,data:l??{},createdAt:new Date().toISOString(),actionType:u})}),await this.refreshUserFlowState());let h=this.getUserFlowState();r.isCompleted=h.stepStates[r.id].actionType==b,r.isStarted=h.stepStates[r.id].actionType==u,r.lastActionAt=new Date},C.complete=async l=>{let r=this.steps.get(f.id);if(r.isCompleted)return;let h=this.getNumberOfCompletedSteps()+1==this.steps.size;r.isCompleted=!0,this.isStarted=!0;let d=F(this.getGlobalState().userFlowStates[this.id]);d.stepStates[r.id].actionType=b,d.stepStates[r.id].lastActionAt=new Date().toISOString(),d.flowState=h?D:A;let O=Array.from(this.steps.keys())[T+1];if(O){d.lastStepId=O,d.stepStates[O].actionType=u;let J=new Date;d.stepStates[O].lastActionAt=J.toISOString(),this.steps.get(O).isStarted=!0,this.steps.get(O).lastActionAt=J}h&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=d,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:r.id,data:l??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState();let W=this.getUserFlowState();r.isCompleted=W.stepStates[r.id].actionType==b,r.isStarted=W.stepStates[r.id].actionType==u,r.lastActionAt=new Date},C.reset=async()=>{let l=this.steps.get(f.id);if(!l.isCompleted)return;l.isCompleted=!1,l.isStarted=!1,l.lastActionAt=void 0;let r=F(this.getGlobalState().userFlowStates[this.id]);r.stepStates[l.id].actionType=v,r.stepStates[l.id].lastActionAt=void 0,r.flowState=A,this.getGlobalState().userFlowStates[this.id]=r,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:l.id,data:{},createdAt:new Date().toISOString(),actionType:v})}),await this.refreshUserFlowState();let g=this.getUserFlowState();l.isCompleted=g.stepStates[l.id].actionType==b,l.isStarted=g.stepStates[l.id].actionType==u,l.lastActionAt=void 0},C.onStateChange=l=>{let r=g=>{if(g.id!==this.id)return;let h=g.steps.get(f.id),d=this.lastStepUpdate.get(l);(h.isCompleted!==(d==null?void 0:d.isCompleted)||h.isStarted!==(d==null?void 0:d.isStarted)||h.isHidden!==(d==null?void 0:d.isHidden)||h.isBlocked!==(d==null?void 0:d.isBlocked))&&(l(h,d??F(h)),this.lastStepUpdate.set(l,F(h)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(l,r),this.getGlobalState().onFlowStateChangeHandlers.push(r)},C.removeStateChangeHandler=l=>{let r=this.getGlobalState().onStepStateChangeHandlerWrappers.get(l);r&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(g=>g!==r))},y.set(f.id,C)}),this.steps=y,Object.keys(this.lastUsedVariables).length>0&&this.applyVariables(this.lastUsedVariables)}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e=F(this.getGlobalState().userFlowStates[this.id]);e.flowState=A,this.getGlobalState().userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:A})}),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,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:D})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=F(this.getGlobalState().userFlowStates[this.id]);t.flowState=D,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,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:G})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async forward(t){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e&&await e.start(t)}async back(t){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&await e.start(t)}async restart(){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:j})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let t=Array.from(this.steps.keys()).find(i=>this.steps.get(i).isCompleted===!1&&this.steps.get(i).isHidden===!1);Array.from(this.steps.keys()).forEach(i=>{var o;this.steps.get(i).isStarted&&this.steps.get(i).lastActionAt&&this.steps.get(i).lastActionAt>(((o=this.steps.get(t))==null?void 0:o.lastActionAt)??new Date(0))&&(t=i)});let e=t??Array.from(this.steps.keys())[0];return this.steps.get(e)}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}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=(i,o)=>{(i.id===this.id&&(i.isCompleted!==o.isCompleted||i.isStarted!==o.isStarted||i.isSkipped!==o.isSkipped||i.isVisible!==o.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(o.steps))&&t(i,o)};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(i=>i!==e))}applyVariables(t){let e=i=>{let o=i.match(/\${(.*?)}/g);return o&&o.forEach(c=>{let n=c.replace("${","").replace("}","");i=i.replace(c,t[n]??"")}),i};this.title=e(this.title??""),this.subtitle=e(this.subtitle??""),this.steps.forEach(i=>{Object.keys(i).forEach(o=>{typeof i[o]=="string"&&(i[o]=e(i[o]))})}),this.lastUsedVariables=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var v="NOT_STARTED_STEP",D="COMPLETED_FLOW",G="SKIPPED_FLOW",A="STARTED_FLOW",j="NOT_STARTED_FLOW",b="COMPLETED_STEP",u="STARTED_STEP",rt="frigade-last-call-at-",nt="frigade-last-call-data-",Y="frigade-guest-key",L="guest_",lt="get-cache-";var dt=1e3,x="fr-js-";function _(s){let a=new w(s.config,s.rawData);return a.isCompleted=s.isCompleted,a.isStarted=s.isStarted,a.isSkipped=s.isSkipped,a.isVisible=s.isVisible,a.steps=s.steps,a}function F(s){return JSON.parse(JSON.stringify(s))}function K(s){return{headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json","X-Frigade-SDK-Version":k,"X-Frigade-SDK-Platform":"Javascript"}}}function N(s){return m()?window.localStorage.getItem(`${x}${s}`):null}function H(s,a){m()&&window.localStorage.setItem(`${x}${s}`,a)}function M(){Object.keys(p).forEach(s=>{s.startsWith(lt)&&delete p[s]})}function q(){m()&&Object.keys(window.localStorage).forEach(s=>{s.startsWith(x)&&window.localStorage.removeItem(s)})}async function $(s,a){let t=rt+s,e=nt+s;if(m()&&a&&a.body&&a.method==="POST"){let o=N(t),c=N(e);if(o&&c&&c==a.body){let n=new Date(o);if(new Date().getTime()-n.getTime()<dt)return S()}H(t,new Date().toISOString()),H(e,a.body),M()}let i;try{i=(0,X.default)(s,a),i=await i}catch(o){return S(o)}if(!i)return S("Received an empty response");if(i.status>=400)return S(i.statusText);try{if(i.status===204||i.status===201)return S();let o=await i.json();return o.error?S(o.error):o}catch(o){return S(o)}}function S(s){return s&&console.log("Call to Frigade failed",s),{json:()=>({})}}function B(){if(m()){let s=N(Y);return s||(s=`${L}${(0,z.v4)()}`,H(Y,s)),s}}function m(){return typeof window<"u"}var P=class extends E{constructor(t,e){super({apiKey:t,...e});this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=async()=>{document.visibilityState==="visible"&&(await this.refreshFlows(),await this.refreshUserFlowStates())};this.init(this.config),m()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(m()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=R(this.config);p[t]&&(p[t].onFlowStateChangeHandlers=[])}}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{var e;await this.refreshUserFlowStates(),await this.refreshFlows(),this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(L))&&await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})})(),this.initPromise}async identify(t,e){this.config={...this.config,userId:t},await this.initIfNeeded(),await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),await this.resync()}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.resync()}async track(t,e){if(await this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})}),await this.resync()}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reload(){q(),M(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,_(t))})})}async resync(){this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,_(t))})})}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}hasFailedToLoad(){return this.hasFailed}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=R(this.config);if(!p[t]){let e=this,i={set:function(o,c,n){return o[c]&&o[c].flowState&&(JSON.stringify(o[c].flowState)!==JSON.stringify(n==null?void 0:n.flowState)||JSON.stringify(o[c].stepStates)!==JSON.stringify(n==null?void 0:n.stepStates)||JSON.stringify(o[c].shouldTrigger)!==JSON.stringify(n==null?void 0:n.shouldTrigger))&&e.triggerEventHandlers(o[c]),o[c]=n,!0}};if(p[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockUserFlowStates(t);return}p[t].refreshUserFlowStates=async()=>{if(this.config.__readOnly)return;let o=await this.fetch(`/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`:""}`);o&&o.data?(o.data.forEach(n=>{let y=!1,f=p[t].userFlowStates[n.flowId];f&&f.shouldTrigger==!1&&n.shouldTrigger==!0&&(y=!0),p[t].userFlowStates[n.flowId]=n,y&&this.flows.forEach(T=>{T.id==n.flowId&&(T.reload(),this.triggerEventHandlers(p[t].userFlowStates[T.id]))})}),this.hasFailed=!1):this.hasFailed=!0}}await p[t].refreshUserFlowStates()}async refreshFlows(){if(this.flows=[],this.config.__flowConfigOverrides){this.mockFlowConfigs();return}let t=await this.fetch("/flows");t&&t.data?t.data.forEach(i=>{this.flows.push(new w(this.config,i)),this.getGlobalState().previousFlows.set(i.slug,_(this.flows[this.flows.length-1]))}):this.hasFailed=!0}mockFlowConfigs(){Object.keys(this.config.__flowConfigOverrides).forEach(t=>{this.flows.push(new w(this.config,{id:-1,name:"",description:"",data:this.config.__flowConfigOverrides[t],createdAt:new Date().toISOString(),modifiedAt:new Date().toISOString(),slug:t,targetingLogic:"",type:"CHECKLIST",triggerType:"MANUAL",status:"ACTIVE",version:1,active:!0}))})}mockUserFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var o;let i=JSON.parse(this.config.__flowConfigOverrides[e]);p[t].userFlowStates[e]={flowId:e,flowState:"NOT_STARTED_FLOW",lastStepId:null,userId:this.config.userId,foreignUserId:this.config.userId,stepStates:((o=i==null?void 0:i.steps)==null?void 0:o.reduce((c,n)=>(c[n.id]={stepId:n.id,flowSlug:e,actionType:"NOT_STARTED_STEP",createdAt:new Date().toISOString(),blocked:!1,hidden:!1},c),{}))??{},shouldTrigger:!1}})}async triggerEventHandlers(t){t&&this.flows.forEach(e=>{e.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(i=>{let o=this.getGlobalState().previousFlows.get(e.id);i(e,o),this.getGlobalState().previousFlows.set(e.id,_(e))})})}};0&&(module.exports={Flow,Frigade});
2
+ var Q=Object.create;var U=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var et=Object.getPrototypeOf,it=Object.prototype.hasOwnProperty;var st=(s,a)=>{for(var t in a)U(s,t,{get:a[t],enumerable:!0})},V=(s,a,t,e)=>{if(a&&typeof a=="object"||typeof a=="function")for(let i of tt(a))!it.call(s,i)&&i!==t&&U(s,i,{get:()=>a[i],enumerable:!(e=Z(a,i))||e.enumerable});return s};var ot=(s,a,t)=>(t=s!=null?Q(et(s)):{},V(a||!s||!s.__esModule?U(t,"default",{value:s,enumerable:!0}):t,s)),at=s=>V(U({},"__esModule",{value:!0}),s);var ct={};st(ct,{Flow:()=>w,Frigade:()=>v});module.exports=at(ct);var k="0.2.20";var X=ot(require("cross-fetch"),1),z=require("uuid");var g={};function D(s){return`${s.__instanceId}-${s.apiKey}:${s.userId??""}:${s.groupId??""}`}var E=class{constructor(a){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:B(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(a).filter(([e,i])=>i!=null));this.config={...this.config,...t}}async fetch(a,t){return this.config.__readOnly?f():$(`${this.config.apiUrl}${a}`,{...t??{},...K(this.config.apiKey)})}getGlobalState(){let a=D(this.config);if(!g[a])throw new Error("Frigade not initialized");return g[a]}};var w=class extends E{constructor(t,e){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.lastUsedVariables={};this.flowDataRaw=e,this.initFromRawData(e)}reload(){this.initFromRawData(this.flowDataRaw)}initFromRawData(t){let e=JSON.parse(t.data),i=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 o=this.getUserFlowState();if(!o)return;this.userFlowStateRaw=o,this.isCompleted=o.flowState==_,this.isStarted=o.flowState==A,this.isSkipped=o.flowState==G;let c=this.isCompleted||this.isSkipped,n=t.targetingLogic&&o.shouldTrigger===!1;this.isVisible=!c&&!n,this.flowDataRaw.active===!1&&(this.isVisible=!1);let y=new Map;i.forEach((S,T)=>{let C=o.stepStates[S.id],I={...S,isCompleted:C.actionType==b,isStarted:C.actionType==u,isHidden:C.hidden,isBlocked:C.blocked,lastActionAt:C.lastActionAt?new Date(C.lastActionAt):void 0,order:T};I.start=async l=>{let r=this.steps.get(S.id);if(this.getCurrentStep().id===r.id&&r.isStarted)return;r.isStarted=!0;let h=F(this.getGlobalState().userFlowStates[this.id]);h.stepStates[r.id].actionType=u,h.stepStates[r.id].lastActionAt=new Date().toISOString(),h.lastStepId=r.id,this.getGlobalState().userFlowStates[this.id]=h,r.isCompleted||(await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:r.id,data:l??{},createdAt:new Date().toISOString(),actionType:u})}),await this.refreshUserFlowState());let p=this.getUserFlowState();r.isCompleted=p.stepStates[r.id].actionType==b,r.isStarted=p.stepStates[r.id].actionType==u,r.lastActionAt=new Date},I.complete=async l=>{let r=this.steps.get(S.id);if(r.isCompleted)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size;r.isCompleted=!0,this.isStarted=!0;let d=F(this.getGlobalState().userFlowStates[this.id]);d.stepStates[r.id].actionType=b,d.stepStates[r.id].lastActionAt=new Date().toISOString(),d.flowState=p?_:A;let O=Array.from(this.steps.keys())[T+1];if(O){d.lastStepId=O,d.stepStates[O].actionType=u;let J=new Date;d.stepStates[O].lastActionAt=J.toISOString(),this.steps.get(O).isStarted=!0,this.steps.get(O).lastActionAt=J}p&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=d,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:r.id,data:l??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState();let W=this.getUserFlowState();r.isCompleted=W.stepStates[r.id].actionType==b,r.isStarted=W.stepStates[r.id].actionType==u,r.lastActionAt=new Date},I.reset=async()=>{let l=this.steps.get(S.id);if(!l.isCompleted)return;l.isCompleted=!1,l.isStarted=!1,l.lastActionAt=void 0;let r=F(this.getGlobalState().userFlowStates[this.id]);r.stepStates[l.id].actionType=P,r.stepStates[l.id].lastActionAt=void 0,r.flowState=A,this.getGlobalState().userFlowStates[this.id]=r,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:l.id,data:{},createdAt:new Date().toISOString(),actionType:P})}),await this.refreshUserFlowState();let h=this.getUserFlowState();l.isCompleted=h.stepStates[l.id].actionType==b,l.isStarted=h.stepStates[l.id].actionType==u,l.lastActionAt=void 0},I.onStateChange=l=>{let r=h=>{if(h.id!==this.id)return;let p=h.steps.get(S.id),d=this.lastStepUpdate.get(l);(p.isCompleted!==(d==null?void 0:d.isCompleted)||p.isStarted!==(d==null?void 0:d.isStarted)||p.isHidden!==(d==null?void 0:d.isHidden)||p.isBlocked!==(d==null?void 0:d.isBlocked))&&(l(p,d??F(p)),this.lastStepUpdate.set(l,F(p)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(l,r),this.getGlobalState().onFlowStateChangeHandlers.push(r)},I.removeStateChangeHandler=l=>{let r=this.getGlobalState().onStepStateChangeHandlerWrappers.get(l);r&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(h=>h!==r))},y.set(S.id,I)}),this.steps=y,Object.keys(this.lastUsedVariables).length>0&&this.applyVariables(this.lastUsedVariables)}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e=F(this.getGlobalState().userFlowStates[this.id]);e.flowState=A,this.getGlobalState().userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:A})}),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,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:_})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=F(this.getGlobalState().userFlowStates[this.id]);t.flowState=_,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,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:G})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async forward(t){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e&&await e.start(t)}async back(t){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&await e.start(t)}async restart(){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:j})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let t=Array.from(this.steps.keys()).find(i=>this.steps.get(i).isCompleted===!1&&this.steps.get(i).isHidden===!1);Array.from(this.steps.keys()).forEach(i=>{var o;this.steps.get(i).isStarted&&this.steps.get(i).lastActionAt&&this.steps.get(i).lastActionAt>(((o=this.steps.get(t))==null?void 0:o.lastActionAt)??new Date(0))&&(t=i)});let e=t??Array.from(this.steps.keys())[0];return this.steps.get(e)}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}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=(i,o)=>{(i.id===this.id&&(i.isCompleted!==o.isCompleted||i.isStarted!==o.isStarted||i.isSkipped!==o.isSkipped||i.isVisible!==o.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(o.steps))&&t(i,o)};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(i=>i!==e))}applyVariables(t){let e=i=>{let o=i.match(/\${(.*?)}/g);return o&&o.forEach(c=>{let n=c.replace("${","").replace("}","");i=i.replace(c,t[n]??"")}),i};this.title=e(this.title??""),this.subtitle=e(this.subtitle??""),this.steps.forEach(i=>{Object.keys(i).forEach(o=>{typeof i[o]=="string"&&(i[o]=e(i[o]))})}),this.lastUsedVariables=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var P="NOT_STARTED_STEP",_="COMPLETED_FLOW",G="SKIPPED_FLOW",A="STARTED_FLOW",j="NOT_STARTED_FLOW",b="COMPLETED_STEP",u="STARTED_STEP",rt="frigade-last-call-at-",nt="frigade-last-call-data-",Y="frigade-guest-key",L="guest_",lt="get-cache-";var dt=1e3,x="fr-js-";function R(s){let a=new w(s.config,s.rawData);return a.isCompleted=s.isCompleted,a.isStarted=s.isStarted,a.isSkipped=s.isSkipped,a.isVisible=s.isVisible,a.steps=s.steps,a}function F(s){return JSON.parse(JSON.stringify(s))}function K(s){return{headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json","X-Frigade-SDK-Version":k,"X-Frigade-SDK-Platform":"Javascript"}}}function N(s){return m()?window.localStorage.getItem(`${x}${s}`):null}function H(s,a){m()&&window.localStorage.setItem(`${x}${s}`,a)}function M(){Object.keys(g).forEach(s=>{s.startsWith(lt)&&delete g[s]})}function q(){m()&&Object.keys(window.localStorage).forEach(s=>{s.startsWith(x)&&window.localStorage.removeItem(s)})}async function $(s,a){let t=rt+s,e=nt+s;if(m()&&a&&a.body&&a.method==="POST"){let o=N(t),c=N(e);if(o&&c&&c==a.body){let n=new Date(o);if(new Date().getTime()-n.getTime()<dt)return f()}H(t,new Date().toISOString()),H(e,a.body),M()}let i;try{i=(0,X.default)(s,a),i=await i}catch(o){return f(o)}if(!i)return f("Received an empty response");if(i.status>=400)return f(i.statusText);try{if(i.status===204||i.status===201)return f();let o=await i.json();return o.error?f(o.error):o}catch(o){return f(o)}}function f(s){return s&&console.log("Call to Frigade failed",s),{json:()=>({})}}function B(){if(m()){let s=N(Y);return s||(s=`${L}${(0,z.v4)()}`,H(Y,s)),s}}function m(){return typeof window<"u"}var v=class extends E{constructor(t,e){super({apiKey:t,...e});this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=async()=>{document.visibilityState==="visible"&&(await this.refreshFlows(),await this.refreshUserFlowStates(),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,R(t))})}))};this.init(this.config),m()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(m()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=D(this.config);g[t]&&(g[t].onFlowStateChangeHandlers=[])}}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{var e;await this.refreshUserFlowStates(),await this.refreshFlows(),this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(L))&&await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})})(),this.initPromise}async identify(t,e){this.config={...this.config,userId:t},await this.initIfNeeded(),await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),await this.resync()}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.resync()}async track(t,e){if(await this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})}),await this.resync()}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reload(){q(),M(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,R(t))})})}async resync(){this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,R(t))})})}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}hasFailedToLoad(){return this.hasFailed}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(!g[t]){let e=this,i={set:function(o,c,n){return o[c]&&o[c].flowState&&(JSON.stringify(o[c].flowState)!==JSON.stringify(n==null?void 0:n.flowState)||JSON.stringify(o[c].stepStates)!==JSON.stringify(n==null?void 0:n.stepStates)||JSON.stringify(o[c].shouldTrigger)!==JSON.stringify(n==null?void 0:n.shouldTrigger))&&e.triggerEventHandlers(o[c]),o[c]=n,!0}};if(g[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockUserFlowStates(t);return}g[t].refreshUserFlowStates=async()=>{if(this.config.__readOnly)return;let o=await this.fetch(`/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`:""}`);o&&o.data?(o.data.forEach(n=>{let y=!1,S=g[t].userFlowStates[n.flowId];S&&S.shouldTrigger==!1&&n.shouldTrigger==!0&&(y=!0),g[t].userFlowStates[n.flowId]=n,y&&this.flows.forEach(T=>{T.id==n.flowId&&(T.reload(),this.triggerEventHandlers(g[t].userFlowStates[T.id]))})}),this.hasFailed=!1):this.hasFailed=!0}}await g[t].refreshUserFlowStates()}async refreshFlows(){if(this.flows=[],this.config.__flowConfigOverrides){this.mockFlowConfigs();return}let t=await this.fetch("/flows");t&&t.data?t.data.forEach(i=>{this.flows.push(new w(this.config,i)),this.getGlobalState().previousFlows.set(i.slug,R(this.flows[this.flows.length-1]))}):this.hasFailed=!0}mockFlowConfigs(){Object.keys(this.config.__flowConfigOverrides).forEach(t=>{this.flows.push(new w(this.config,{id:-1,name:"",description:"",data:this.config.__flowConfigOverrides[t],createdAt:new Date().toISOString(),modifiedAt:new Date().toISOString(),slug:t,targetingLogic:"",type:"CHECKLIST",triggerType:"MANUAL",status:"ACTIVE",version:1,active:!0}))})}mockUserFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var o;let i=JSON.parse(this.config.__flowConfigOverrides[e]);g[t].userFlowStates[e]={flowId:e,flowState:"NOT_STARTED_FLOW",lastStepId:null,userId:this.config.userId,foreignUserId:this.config.userId,stepStates:((o=i==null?void 0:i.steps)==null?void 0:o.reduce((c,n)=>(c[n.id]={stepId:n.id,flowSlug:e,actionType:"NOT_STARTED_STEP",createdAt:new Date().toISOString(),blocked:!1,hidden:!1},c),{}))??{},shouldTrigger:!1}})}async triggerEventHandlers(t){t&&this.flows.forEach(e=>{e.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(i=>{let o=this.getGlobalState().previousFlows.get(e.id);i(e,o),this.getGlobalState().previousFlows.set(e.id,R(e))})})}};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.20'\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'\nexport const 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 let response\n try {\n response = fetch(url, options)\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 if (response.status === 204 || response.status === 201) {\n return getEmptyResponse()\n }\n\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\nexport function 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, getEmptyResponse, 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 /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n /**\n * @ignore\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 NOT_STARTED_STEP,\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's ID.\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object.\n * @ignore\n */\n public configYmlAsJson: any\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The metadata of the Flow.\n * @ignore\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 * @ignore\n */\n private readonly flowDataRaw: FlowDataRaw\n /**\n * @ignore\n */\n private userFlowStateRaw?: UserFlowState\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n /**\n * @ignore\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 /**\n * Reload the Flow data from the server\n */\n reload() {\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * @ignore\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 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 if (this.flowDataRaw.active === false) {\n this.isVisible = false\n }\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 lastActionAt: userFlowStateStep.lastActionAt\n ? new Date(userFlowStateStep.lastActionAt)\n : undefined,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.isStarted) {\n return\n }\n\n thisStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[thisStep.id].actionType = STARTED_STEP\n copy.stepStates[thisStep.id].lastActionAt = new Date().toISOString()\n copy.lastStepId = thisStep.id\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n if (!thisStep.isCompleted) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = new Date()\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (thisStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n thisStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[thisStep.id].actionType = COMPLETED_STEP\n copy.stepStates[thisStep.id].lastActionAt = new Date().toISOString()\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 copy.stepStates[nextStepId].actionType = STARTED_STEP\n const lastAction = new Date()\n copy.stepStates[nextStepId].lastActionAt = lastAction.toISOString()\n this.steps.get(nextStepId).isStarted = true\n this.steps.get(nextStepId).lastActionAt = lastAction\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 foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = new Date()\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.isCompleted) {\n return\n }\n\n thisStep.isCompleted = false\n thisStep.isStarted = false\n thisStep.lastActionAt = undefined\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[thisStep.id].actionType = NOT_STARTED_STEP\n copy.stepStates[thisStep.id].lastActionAt = undefined\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 foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = undefined\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 thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.isCompleted !== previousStep?.isCompleted ||\n thisStep.isStarted !== previousStep?.isStarted ||\n thisStep.isHidden !== previousStep?.isHidden ||\n thisStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\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 * 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 foreignUserGroupId: this.config.groupId,\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 * 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 foreignUserGroupId: this.config.groupId,\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 /**\n * @ignore\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 * 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 foreignUserGroupId: this.config.groupId,\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 * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: Record<string | number, any>) {\n const nextStep = this.getStepByIndex(this.getCurrentStepIndex() + 1)\n if (nextStep) {\n await nextStep.start(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: Record<string | number, any>) {\n const previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\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 * Gets current step\n */\n public getCurrentStep(): FlowStep {\n let maybeCurrentStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false && this.steps.get(key).isHidden === false\n )\n Array.from(this.steps.keys()).forEach((key) => {\n if (\n this.steps.get(key).isStarted &&\n this.steps.get(key).lastActionAt &&\n this.steps.get(key).lastActionAt >\n (this.steps.get(maybeCurrentStepId)?.lastActionAt ?? new Date(0))\n ) {\n maybeCurrentStepId = key\n }\n })\n\n const currentStepId = maybeCurrentStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\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 /**\n * @ignore\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 /**\n * @ignore\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 /**\n * @ignore\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 /**\n * @ignore\n */\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { clearCache, cloneFlow, GUEST_PREFIX, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { FlowDataRaw, FlowStatus, FlowType, TriggerType } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshFlows()\n await this.refreshUserFlowStates()\n }\n }\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n }\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\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 if (this.config.userId && !this.config.userId?.startsWith(GUEST_PREFIX)) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n }),\n })\n }\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { ...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.resync()\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = groupId\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.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n } else if (this.config.userId) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\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 private async resync() {\n this.initPromise = null\n await this.init(this.config)\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 /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @param handler\n */\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\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 /**\n * @ignore\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 /**\n * @ignore\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\n if (this.config.__readOnly && this.config.__flowConfigOverrides) {\n this.mockUserFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n if (this.config.__readOnly) {\n return\n }\n\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${\n this.config.groupId\n ? `&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`\n : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n let shouldReload = false\n const before = frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId]\n\n // Special case: for flows that show up based on targeting logic/rules, we need to check if the flow should be triggered\n if (before && before.shouldTrigger == false && userFlowState.shouldTrigger == true) {\n shouldReload = true\n }\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n if (shouldReload) {\n this.flows.forEach((flow) => {\n if (flow.id == userFlowState.flowId) {\n flow.reload()\n this.triggerEventHandlers(\n frigadeGlobalState[globalStateKey].userFlowStates[flow.id]\n )\n }\n })\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n /**\n * @ignore\n */\n private async refreshFlows() {\n this.flows = []\n\n if (this.config.__flowConfigOverrides) {\n this.mockFlowConfigs()\n return\n }\n\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 } else {\n this.hasFailed = true\n }\n }\n\n /**\n * @ignore\n */\n private mockFlowConfigs() {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n this.flows.push(\n new Flow(this.config, {\n id: -1,\n name: '',\n description: '',\n data: this.config.__flowConfigOverrides[flowId],\n createdAt: new Date().toISOString(),\n modifiedAt: new Date().toISOString(),\n slug: flowId,\n targetingLogic: '',\n type: FlowType.CHECKLIST,\n triggerType: TriggerType.MANUAL,\n status: FlowStatus.ACTIVE,\n version: 1,\n active: true,\n })\n )\n })\n }\n\n /**\n * @ignore\n */\n private mockUserFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n const parsed = JSON.parse(this.config.__flowConfigOverrides[flowId])\n frigadeGlobalState[globalStateKey].userFlowStates[flowId] = {\n flowId,\n flowState: 'NOT_STARTED_FLOW',\n lastStepId: null,\n userId: this.config.userId,\n foreignUserId: this.config.userId,\n stepStates:\n parsed?.steps?.reduce((acc, step) => {\n acc[step.id] = {\n stepId: step.id,\n flowSlug: flowId,\n actionType: 'NOT_STARTED_STEP',\n createdAt: new Date().toISOString(),\n blocked: false,\n hidden: false,\n }\n return acc\n }, {}) ?? {},\n shouldTrigger: false,\n }\n })\n }\n\n /**\n * @ignore\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","getEmptyResponse","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","thisStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","lastAction","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","h","nextStep","NOT_STARTED_FLOW","maybeCurrentStepId","key","_a","currentStepId","currentStep","previousFlow","variables","replaceVariables","str","matches","match","variable","NOT_STARTED_STEP","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","POST_CACHE_TTL_MS","LOCAL_STORAGE_PREFIX","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","clearCache","frigadeGlobalState","key","GET_CACHE_PREFIX","resetAllLocalStorage","isWeb","LOCAL_STORAGE_PREFIX","gracefulFetch","url","options","lastCallAtKey","LAST_POST_CALL_AT","lastCallDataKey","LAST_POST_CALL_DATA","lastCall","getLocalStorage","lastCallData","lastCallDate","POST_CACHE_TTL_MS","getEmptyResponse","setLocalStorage","response","fetch","error","body","e","generateGuestId","guestId","GUEST_KEY","GUEST_PREFIX","uuidv4","isWeb","Frigade","Fetchable","apiKey","config","isWeb","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","groupId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","that","validator","target","key","value","userFlowStatesRaw","userFlowState","shouldReload","before","flowDataRaw","flowData","Flow","parsed","acc","step","previousUserFlowState"]}
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.20'\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'\nexport const 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 let response\n try {\n response = fetch(url, options)\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 if (response.status === 204 || response.status === 201) {\n return getEmptyResponse()\n }\n\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\nexport function 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, getEmptyResponse, 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 /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n /**\n * @ignore\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 NOT_STARTED_STEP,\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's ID.\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object.\n * @ignore\n */\n public configYmlAsJson: any\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The metadata of the Flow.\n * @ignore\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 * @ignore\n */\n private readonly flowDataRaw: FlowDataRaw\n /**\n * @ignore\n */\n private userFlowStateRaw?: UserFlowState\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n /**\n * @ignore\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 /**\n * Reload the Flow data from the server\n */\n reload() {\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * @ignore\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 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 if (this.flowDataRaw.active === false) {\n this.isVisible = false\n }\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 lastActionAt: userFlowStateStep.lastActionAt\n ? new Date(userFlowStateStep.lastActionAt)\n : undefined,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.isStarted) {\n return\n }\n\n thisStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[thisStep.id].actionType = STARTED_STEP\n copy.stepStates[thisStep.id].lastActionAt = new Date().toISOString()\n copy.lastStepId = thisStep.id\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n if (!thisStep.isCompleted) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = new Date()\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (thisStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n thisStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[thisStep.id].actionType = COMPLETED_STEP\n copy.stepStates[thisStep.id].lastActionAt = new Date().toISOString()\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 copy.stepStates[nextStepId].actionType = STARTED_STEP\n const lastAction = new Date()\n copy.stepStates[nextStepId].lastActionAt = lastAction.toISOString()\n this.steps.get(nextStepId).isStarted = true\n this.steps.get(nextStepId).lastActionAt = lastAction\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 foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = new Date()\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.isCompleted) {\n return\n }\n\n thisStep.isCompleted = false\n thisStep.isStarted = false\n thisStep.lastActionAt = undefined\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[thisStep.id].actionType = NOT_STARTED_STEP\n copy.stepStates[thisStep.id].lastActionAt = undefined\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 foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = undefined\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 thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.isCompleted !== previousStep?.isCompleted ||\n thisStep.isStarted !== previousStep?.isStarted ||\n thisStep.isHidden !== previousStep?.isHidden ||\n thisStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\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 * 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 foreignUserGroupId: this.config.groupId,\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 * 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 foreignUserGroupId: this.config.groupId,\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 /**\n * @ignore\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 * 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 foreignUserGroupId: this.config.groupId,\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 * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: Record<string | number, any>) {\n const nextStep = this.getStepByIndex(this.getCurrentStepIndex() + 1)\n if (nextStep) {\n await nextStep.start(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: Record<string | number, any>) {\n const previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\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 * Gets current step\n */\n public getCurrentStep(): FlowStep {\n let maybeCurrentStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false && this.steps.get(key).isHidden === false\n )\n Array.from(this.steps.keys()).forEach((key) => {\n if (\n this.steps.get(key).isStarted &&\n this.steps.get(key).lastActionAt &&\n this.steps.get(key).lastActionAt >\n (this.steps.get(maybeCurrentStepId)?.lastActionAt ?? new Date(0))\n ) {\n maybeCurrentStepId = key\n }\n })\n\n const currentStepId = maybeCurrentStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\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 /**\n * @ignore\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 /**\n * @ignore\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 /**\n * @ignore\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 /**\n * @ignore\n */\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { clearCache, cloneFlow, GUEST_PREFIX, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { FlowDataRaw, FlowStatus, FlowType, TriggerType } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshFlows()\n await this.refreshUserFlowStates()\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\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n }\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\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 if (this.config.userId && !this.config.userId?.startsWith(GUEST_PREFIX)) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n }),\n })\n }\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { ...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.resync()\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = groupId\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.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n } else if (this.config.userId) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\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 private async resync() {\n this.initPromise = null\n await this.init(this.config)\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 /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @param handler\n */\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\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 /**\n * @ignore\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 /**\n * @ignore\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\n if (this.config.__readOnly && this.config.__flowConfigOverrides) {\n this.mockUserFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n if (this.config.__readOnly) {\n return\n }\n\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${\n this.config.groupId\n ? `&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`\n : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n let shouldReload = false\n const before = frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId]\n\n // Special case: for flows that show up based on targeting logic/rules, we need to check if the flow should be triggered\n if (before && before.shouldTrigger == false && userFlowState.shouldTrigger == true) {\n shouldReload = true\n }\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n if (shouldReload) {\n this.flows.forEach((flow) => {\n if (flow.id == userFlowState.flowId) {\n flow.reload()\n this.triggerEventHandlers(\n frigadeGlobalState[globalStateKey].userFlowStates[flow.id]\n )\n }\n })\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n /**\n * @ignore\n */\n private async refreshFlows() {\n this.flows = []\n\n if (this.config.__flowConfigOverrides) {\n this.mockFlowConfigs()\n return\n }\n\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 } else {\n this.hasFailed = true\n }\n }\n\n /**\n * @ignore\n */\n private mockFlowConfigs() {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n this.flows.push(\n new Flow(this.config, {\n id: -1,\n name: '',\n description: '',\n data: this.config.__flowConfigOverrides[flowId],\n createdAt: new Date().toISOString(),\n modifiedAt: new Date().toISOString(),\n slug: flowId,\n targetingLogic: '',\n type: FlowType.CHECKLIST,\n triggerType: TriggerType.MANUAL,\n status: FlowStatus.ACTIVE,\n version: 1,\n active: true,\n })\n )\n })\n }\n\n /**\n * @ignore\n */\n private mockUserFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n const parsed = JSON.parse(this.config.__flowConfigOverrides[flowId])\n frigadeGlobalState[globalStateKey].userFlowStates[flowId] = {\n flowId,\n flowState: 'NOT_STARTED_FLOW',\n lastStepId: null,\n userId: this.config.userId,\n foreignUserId: this.config.userId,\n stepStates:\n parsed?.steps?.reduce((acc, step) => {\n acc[step.id] = {\n stepId: step.id,\n flowSlug: flowId,\n actionType: 'NOT_STARTED_STEP',\n createdAt: new Date().toISOString(),\n blocked: false,\n hidden: false,\n }\n return acc\n }, {}) ?? {},\n shouldTrigger: false,\n }\n })\n }\n\n /**\n * @ignore\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","getEmptyResponse","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","thisStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","lastAction","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","nextStep","NOT_STARTED_FLOW","maybeCurrentStepId","key","_a","currentStepId","currentStep","previousFlow","h","variables","replaceVariables","str","matches","match","variable","NOT_STARTED_STEP","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","POST_CACHE_TTL_MS","LOCAL_STORAGE_PREFIX","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","clearCache","frigadeGlobalState","key","GET_CACHE_PREFIX","resetAllLocalStorage","isWeb","LOCAL_STORAGE_PREFIX","gracefulFetch","url","options","lastCallAtKey","LAST_POST_CALL_AT","lastCallDataKey","LAST_POST_CALL_DATA","lastCall","getLocalStorage","lastCallData","lastCallDate","POST_CACHE_TTL_MS","getEmptyResponse","setLocalStorage","response","fetch","error","body","e","generateGuestId","guestId","GUEST_KEY","GUEST_PREFIX","uuidv4","isWeb","Frigade","Fetchable","apiKey","config","flow","handler","lastFlow","cloneFlow","isWeb","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","groupId","event","flowId","resetAllLocalStorage","clearCache","h","that","validator","target","key","value","userFlowStatesRaw","userFlowState","shouldReload","before","flowDataRaw","flowData","Flow","parsed","acc","step","previousUserFlowState"]}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- var J="0.2.20";import Y from"cross-fetch";import{v4 as X}from"uuid";var p={};function R(o){return`${o.__instanceId}-${o.apiKey}:${o.userId??""}:${o.groupId??""}`}var E=class{constructor(n){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:K(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(n).filter(([e,i])=>i!=null));this.config={...this.config,...t}}async fetch(n,t){return this.config.__readOnly?S():k(`${this.config.apiUrl}${n}`,{...t??{},...V(this.config.apiKey)})}getGlobalState(){let n=R(this.config);if(!p[n])throw new Error("Frigade not initialized");return p[n]}};var F=class extends E{constructor(t,e){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.lastUsedVariables={};this.flowDataRaw=e,this.initFromRawData(e)}reload(){this.initFromRawData(this.flowDataRaw)}initFromRawData(t){let e=JSON.parse(t.data),i=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 s=this.getUserFlowState();if(!s)return;this.userFlowStateRaw=s,this.isCompleted=s.flowState==D,this.isStarted=s.flowState==A,this.isSkipped=s.flowState==P;let c=this.isCompleted||this.isSkipped,r=t.targetingLogic&&s.shouldTrigger===!1;this.isVisible=!c&&!r,this.flowDataRaw.active===!1&&(this.isVisible=!1);let y=new Map;i.forEach((f,T)=>{let I=s.stepStates[f.id],C={...f,isCompleted:I.actionType==b,isStarted:I.actionType==w,isHidden:I.hidden,isBlocked:I.blocked,lastActionAt:I.lastActionAt?new Date(I.lastActionAt):void 0,order:T};C.start=async l=>{let a=this.steps.get(f.id);if(this.getCurrentStep().id===a.id&&a.isStarted)return;a.isStarted=!0;let g=u(this.getGlobalState().userFlowStates[this.id]);g.stepStates[a.id].actionType=w,g.stepStates[a.id].lastActionAt=new Date().toISOString(),g.lastStepId=a.id,this.getGlobalState().userFlowStates[this.id]=g,a.isCompleted||(await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:a.id,data:l??{},createdAt:new Date().toISOString(),actionType:w})}),await this.refreshUserFlowState());let h=this.getUserFlowState();a.isCompleted=h.stepStates[a.id].actionType==b,a.isStarted=h.stepStates[a.id].actionType==w,a.lastActionAt=new Date},C.complete=async l=>{let a=this.steps.get(f.id);if(a.isCompleted)return;let h=this.getNumberOfCompletedSteps()+1==this.steps.size;a.isCompleted=!0,this.isStarted=!0;let d=u(this.getGlobalState().userFlowStates[this.id]);d.stepStates[a.id].actionType=b,d.stepStates[a.id].lastActionAt=new Date().toISOString(),d.flowState=h?D:A;let O=Array.from(this.steps.keys())[T+1];if(O){d.lastStepId=O,d.stepStates[O].actionType=w;let W=new Date;d.stepStates[O].lastActionAt=W.toISOString(),this.steps.get(O).isStarted=!0,this.steps.get(O).lastActionAt=W}h&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=d,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:a.id,data:l??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState();let M=this.getUserFlowState();a.isCompleted=M.stepStates[a.id].actionType==b,a.isStarted=M.stepStates[a.id].actionType==w,a.lastActionAt=new Date},C.reset=async()=>{let l=this.steps.get(f.id);if(!l.isCompleted)return;l.isCompleted=!1,l.isStarted=!1,l.lastActionAt=void 0;let a=u(this.getGlobalState().userFlowStates[this.id]);a.stepStates[l.id].actionType=U,a.stepStates[l.id].lastActionAt=void 0,a.flowState=A,this.getGlobalState().userFlowStates[this.id]=a,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:l.id,data:{},createdAt:new Date().toISOString(),actionType:U})}),await this.refreshUserFlowState();let g=this.getUserFlowState();l.isCompleted=g.stepStates[l.id].actionType==b,l.isStarted=g.stepStates[l.id].actionType==w,l.lastActionAt=void 0},C.onStateChange=l=>{let a=g=>{if(g.id!==this.id)return;let h=g.steps.get(f.id),d=this.lastStepUpdate.get(l);(h.isCompleted!==(d==null?void 0:d.isCompleted)||h.isStarted!==(d==null?void 0:d.isStarted)||h.isHidden!==(d==null?void 0:d.isHidden)||h.isBlocked!==(d==null?void 0:d.isBlocked))&&(l(h,d??u(h)),this.lastStepUpdate.set(l,u(h)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(l,a),this.getGlobalState().onFlowStateChangeHandlers.push(a)},C.removeStateChangeHandler=l=>{let a=this.getGlobalState().onStepStateChangeHandlerWrappers.get(l);a&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(g=>g!==a))},y.set(f.id,C)}),this.steps=y,Object.keys(this.lastUsedVariables).length>0&&this.applyVariables(this.lastUsedVariables)}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e=u(this.getGlobalState().userFlowStates[this.id]);e.flowState=A,this.getGlobalState().userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:A})}),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,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:D})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=u(this.getGlobalState().userFlowStates[this.id]);t.flowState=D,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,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:P})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async forward(t){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e&&await e.start(t)}async back(t){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&await e.start(t)}async restart(){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:$})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let t=Array.from(this.steps.keys()).find(i=>this.steps.get(i).isCompleted===!1&&this.steps.get(i).isHidden===!1);Array.from(this.steps.keys()).forEach(i=>{var s;this.steps.get(i).isStarted&&this.steps.get(i).lastActionAt&&this.steps.get(i).lastActionAt>(((s=this.steps.get(t))==null?void 0:s.lastActionAt)??new Date(0))&&(t=i)});let e=t??Array.from(this.steps.keys())[0];return this.steps.get(e)}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}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=(i,s)=>{(i.id===this.id&&(i.isCompleted!==s.isCompleted||i.isStarted!==s.isStarted||i.isSkipped!==s.isSkipped||i.isVisible!==s.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(s.steps))&&t(i,s)};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(i=>i!==e))}applyVariables(t){let e=i=>{let s=i.match(/\${(.*?)}/g);return s&&s.forEach(c=>{let r=c.replace("${","").replace("}","");i=i.replace(c,t[r]??"")}),i};this.title=e(this.title??""),this.subtitle=e(this.subtitle??""),this.steps.forEach(i=>{Object.keys(i).forEach(s=>{typeof i[s]=="string"&&(i[s]=e(i[s]))})}),this.lastUsedVariables=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var U="NOT_STARTED_STEP",D="COMPLETED_FLOW",P="SKIPPED_FLOW",A="STARTED_FLOW",$="NOT_STARTED_FLOW",b="COMPLETED_STEP",w="STARTED_STEP",z="frigade-last-call-at-",q="frigade-last-call-data-",B="frigade-guest-key",N="guest_",Q="get-cache-";var Z=1e3,H="fr-js-";function _(o){let n=new F(o.config,o.rawData);return n.isCompleted=o.isCompleted,n.isStarted=o.isStarted,n.isSkipped=o.isSkipped,n.isVisible=o.isVisible,n.steps=o.steps,n}function u(o){return JSON.parse(JSON.stringify(o))}function V(o){return{headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","X-Frigade-SDK-Version":J,"X-Frigade-SDK-Platform":"Javascript"}}}function v(o){return m()?window.localStorage.getItem(`${H}${o}`):null}function G(o,n){m()&&window.localStorage.setItem(`${H}${o}`,n)}function L(){Object.keys(p).forEach(o=>{o.startsWith(Q)&&delete p[o]})}function j(){m()&&Object.keys(window.localStorage).forEach(o=>{o.startsWith(H)&&window.localStorage.removeItem(o)})}async function k(o,n){let t=z+o,e=q+o;if(m()&&n&&n.body&&n.method==="POST"){let s=v(t),c=v(e);if(s&&c&&c==n.body){let r=new Date(s);if(new Date().getTime()-r.getTime()<Z)return S()}G(t,new Date().toISOString()),G(e,n.body),L()}let i;try{i=Y(o,n),i=await i}catch(s){return S(s)}if(!i)return S("Received an empty response");if(i.status>=400)return S(i.statusText);try{if(i.status===204||i.status===201)return S();let s=await i.json();return s.error?S(s.error):s}catch(s){return S(s)}}function S(o){return o&&console.log("Call to Frigade failed",o),{json:()=>({})}}function K(){if(m()){let o=v(B);return o||(o=`${N}${X()}`,G(B,o)),o}}function m(){return typeof window<"u"}var x=class extends E{constructor(t,e){super({apiKey:t,...e});this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=async()=>{document.visibilityState==="visible"&&(await this.refreshFlows(),await this.refreshUserFlowStates())};this.init(this.config),m()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(m()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=R(this.config);p[t]&&(p[t].onFlowStateChangeHandlers=[])}}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{var e;await this.refreshUserFlowStates(),await this.refreshFlows(),this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(N))&&await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})})(),this.initPromise}async identify(t,e){this.config={...this.config,userId:t},await this.initIfNeeded(),await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),await this.resync()}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.resync()}async track(t,e){if(await this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})}),await this.resync()}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reload(){j(),L(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,_(t))})})}async resync(){this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,_(t))})})}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}hasFailedToLoad(){return this.hasFailed}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=R(this.config);if(!p[t]){let e=this,i={set:function(s,c,r){return s[c]&&s[c].flowState&&(JSON.stringify(s[c].flowState)!==JSON.stringify(r==null?void 0:r.flowState)||JSON.stringify(s[c].stepStates)!==JSON.stringify(r==null?void 0:r.stepStates)||JSON.stringify(s[c].shouldTrigger)!==JSON.stringify(r==null?void 0:r.shouldTrigger))&&e.triggerEventHandlers(s[c]),s[c]=r,!0}};if(p[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockUserFlowStates(t);return}p[t].refreshUserFlowStates=async()=>{if(this.config.__readOnly)return;let s=await this.fetch(`/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`:""}`);s&&s.data?(s.data.forEach(r=>{let y=!1,f=p[t].userFlowStates[r.flowId];f&&f.shouldTrigger==!1&&r.shouldTrigger==!0&&(y=!0),p[t].userFlowStates[r.flowId]=r,y&&this.flows.forEach(T=>{T.id==r.flowId&&(T.reload(),this.triggerEventHandlers(p[t].userFlowStates[T.id]))})}),this.hasFailed=!1):this.hasFailed=!0}}await p[t].refreshUserFlowStates()}async refreshFlows(){if(this.flows=[],this.config.__flowConfigOverrides){this.mockFlowConfigs();return}let t=await this.fetch("/flows");t&&t.data?t.data.forEach(i=>{this.flows.push(new F(this.config,i)),this.getGlobalState().previousFlows.set(i.slug,_(this.flows[this.flows.length-1]))}):this.hasFailed=!0}mockFlowConfigs(){Object.keys(this.config.__flowConfigOverrides).forEach(t=>{this.flows.push(new F(this.config,{id:-1,name:"",description:"",data:this.config.__flowConfigOverrides[t],createdAt:new Date().toISOString(),modifiedAt:new Date().toISOString(),slug:t,targetingLogic:"",type:"CHECKLIST",triggerType:"MANUAL",status:"ACTIVE",version:1,active:!0}))})}mockUserFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var s;let i=JSON.parse(this.config.__flowConfigOverrides[e]);p[t].userFlowStates[e]={flowId:e,flowState:"NOT_STARTED_FLOW",lastStepId:null,userId:this.config.userId,foreignUserId:this.config.userId,stepStates:((s=i==null?void 0:i.steps)==null?void 0:s.reduce((c,r)=>(c[r.id]={stepId:r.id,flowSlug:e,actionType:"NOT_STARTED_STEP",createdAt:new Date().toISOString(),blocked:!1,hidden:!1},c),{}))??{},shouldTrigger:!1}})}async triggerEventHandlers(t){t&&this.flows.forEach(e=>{e.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(i=>{let s=this.getGlobalState().previousFlows.get(e.id);i(e,s),this.getGlobalState().previousFlows.set(e.id,_(e))})})}};export{F as Flow,x as Frigade};
2
+ var J="0.2.20";import Y from"cross-fetch";import{v4 as X}from"uuid";var g={};function D(o){return`${o.__instanceId}-${o.apiKey}:${o.userId??""}:${o.groupId??""}`}var E=class{constructor(n){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:K(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(n).filter(([e,i])=>i!=null));this.config={...this.config,...t}}async fetch(n,t){return this.config.__readOnly?f():k(`${this.config.apiUrl}${n}`,{...t??{},...V(this.config.apiKey)})}getGlobalState(){let n=D(this.config);if(!g[n])throw new Error("Frigade not initialized");return g[n]}};var F=class extends E{constructor(t,e){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.lastUsedVariables={};this.flowDataRaw=e,this.initFromRawData(e)}reload(){this.initFromRawData(this.flowDataRaw)}initFromRawData(t){let e=JSON.parse(t.data),i=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 s=this.getUserFlowState();if(!s)return;this.userFlowStateRaw=s,this.isCompleted=s.flowState==_,this.isStarted=s.flowState==A,this.isSkipped=s.flowState==v;let c=this.isCompleted||this.isSkipped,r=t.targetingLogic&&s.shouldTrigger===!1;this.isVisible=!c&&!r,this.flowDataRaw.active===!1&&(this.isVisible=!1);let y=new Map;i.forEach((S,T)=>{let C=s.stepStates[S.id],I={...S,isCompleted:C.actionType==b,isStarted:C.actionType==w,isHidden:C.hidden,isBlocked:C.blocked,lastActionAt:C.lastActionAt?new Date(C.lastActionAt):void 0,order:T};I.start=async l=>{let a=this.steps.get(S.id);if(this.getCurrentStep().id===a.id&&a.isStarted)return;a.isStarted=!0;let h=u(this.getGlobalState().userFlowStates[this.id]);h.stepStates[a.id].actionType=w,h.stepStates[a.id].lastActionAt=new Date().toISOString(),h.lastStepId=a.id,this.getGlobalState().userFlowStates[this.id]=h,a.isCompleted||(await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:a.id,data:l??{},createdAt:new Date().toISOString(),actionType:w})}),await this.refreshUserFlowState());let p=this.getUserFlowState();a.isCompleted=p.stepStates[a.id].actionType==b,a.isStarted=p.stepStates[a.id].actionType==w,a.lastActionAt=new Date},I.complete=async l=>{let a=this.steps.get(S.id);if(a.isCompleted)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size;a.isCompleted=!0,this.isStarted=!0;let d=u(this.getGlobalState().userFlowStates[this.id]);d.stepStates[a.id].actionType=b,d.stepStates[a.id].lastActionAt=new Date().toISOString(),d.flowState=p?_:A;let O=Array.from(this.steps.keys())[T+1];if(O){d.lastStepId=O,d.stepStates[O].actionType=w;let W=new Date;d.stepStates[O].lastActionAt=W.toISOString(),this.steps.get(O).isStarted=!0,this.steps.get(O).lastActionAt=W}p&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=d,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:a.id,data:l??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState();let M=this.getUserFlowState();a.isCompleted=M.stepStates[a.id].actionType==b,a.isStarted=M.stepStates[a.id].actionType==w,a.lastActionAt=new Date},I.reset=async()=>{let l=this.steps.get(S.id);if(!l.isCompleted)return;l.isCompleted=!1,l.isStarted=!1,l.lastActionAt=void 0;let a=u(this.getGlobalState().userFlowStates[this.id]);a.stepStates[l.id].actionType=U,a.stepStates[l.id].lastActionAt=void 0,a.flowState=A,this.getGlobalState().userFlowStates[this.id]=a,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:l.id,data:{},createdAt:new Date().toISOString(),actionType:U})}),await this.refreshUserFlowState();let h=this.getUserFlowState();l.isCompleted=h.stepStates[l.id].actionType==b,l.isStarted=h.stepStates[l.id].actionType==w,l.lastActionAt=void 0},I.onStateChange=l=>{let a=h=>{if(h.id!==this.id)return;let p=h.steps.get(S.id),d=this.lastStepUpdate.get(l);(p.isCompleted!==(d==null?void 0:d.isCompleted)||p.isStarted!==(d==null?void 0:d.isStarted)||p.isHidden!==(d==null?void 0:d.isHidden)||p.isBlocked!==(d==null?void 0:d.isBlocked))&&(l(p,d??u(p)),this.lastStepUpdate.set(l,u(p)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(l,a),this.getGlobalState().onFlowStateChangeHandlers.push(a)},I.removeStateChangeHandler=l=>{let a=this.getGlobalState().onStepStateChangeHandlerWrappers.get(l);a&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(h=>h!==a))},y.set(S.id,I)}),this.steps=y,Object.keys(this.lastUsedVariables).length>0&&this.applyVariables(this.lastUsedVariables)}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e=u(this.getGlobalState().userFlowStates[this.id]);e.flowState=A,this.getGlobalState().userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:A})}),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,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:_})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=u(this.getGlobalState().userFlowStates[this.id]);t.flowState=_,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,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:v})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async forward(t){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e&&await e.start(t)}async back(t){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&await e.start(t)}async restart(){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:$})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let t=Array.from(this.steps.keys()).find(i=>this.steps.get(i).isCompleted===!1&&this.steps.get(i).isHidden===!1);Array.from(this.steps.keys()).forEach(i=>{var s;this.steps.get(i).isStarted&&this.steps.get(i).lastActionAt&&this.steps.get(i).lastActionAt>(((s=this.steps.get(t))==null?void 0:s.lastActionAt)??new Date(0))&&(t=i)});let e=t??Array.from(this.steps.keys())[0];return this.steps.get(e)}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}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=(i,s)=>{(i.id===this.id&&(i.isCompleted!==s.isCompleted||i.isStarted!==s.isStarted||i.isSkipped!==s.isSkipped||i.isVisible!==s.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(s.steps))&&t(i,s)};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(i=>i!==e))}applyVariables(t){let e=i=>{let s=i.match(/\${(.*?)}/g);return s&&s.forEach(c=>{let r=c.replace("${","").replace("}","");i=i.replace(c,t[r]??"")}),i};this.title=e(this.title??""),this.subtitle=e(this.subtitle??""),this.steps.forEach(i=>{Object.keys(i).forEach(s=>{typeof i[s]=="string"&&(i[s]=e(i[s]))})}),this.lastUsedVariables=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var U="NOT_STARTED_STEP",_="COMPLETED_FLOW",v="SKIPPED_FLOW",A="STARTED_FLOW",$="NOT_STARTED_FLOW",b="COMPLETED_STEP",w="STARTED_STEP",z="frigade-last-call-at-",q="frigade-last-call-data-",B="frigade-guest-key",N="guest_",Q="get-cache-";var Z=1e3,H="fr-js-";function R(o){let n=new F(o.config,o.rawData);return n.isCompleted=o.isCompleted,n.isStarted=o.isStarted,n.isSkipped=o.isSkipped,n.isVisible=o.isVisible,n.steps=o.steps,n}function u(o){return JSON.parse(JSON.stringify(o))}function V(o){return{headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","X-Frigade-SDK-Version":J,"X-Frigade-SDK-Platform":"Javascript"}}}function P(o){return m()?window.localStorage.getItem(`${H}${o}`):null}function G(o,n){m()&&window.localStorage.setItem(`${H}${o}`,n)}function L(){Object.keys(g).forEach(o=>{o.startsWith(Q)&&delete g[o]})}function j(){m()&&Object.keys(window.localStorage).forEach(o=>{o.startsWith(H)&&window.localStorage.removeItem(o)})}async function k(o,n){let t=z+o,e=q+o;if(m()&&n&&n.body&&n.method==="POST"){let s=P(t),c=P(e);if(s&&c&&c==n.body){let r=new Date(s);if(new Date().getTime()-r.getTime()<Z)return f()}G(t,new Date().toISOString()),G(e,n.body),L()}let i;try{i=Y(o,n),i=await i}catch(s){return f(s)}if(!i)return f("Received an empty response");if(i.status>=400)return f(i.statusText);try{if(i.status===204||i.status===201)return f();let s=await i.json();return s.error?f(s.error):s}catch(s){return f(s)}}function f(o){return o&&console.log("Call to Frigade failed",o),{json:()=>({})}}function K(){if(m()){let o=P(B);return o||(o=`${N}${X()}`,G(B,o)),o}}function m(){return typeof window<"u"}var x=class extends E{constructor(t,e){super({apiKey:t,...e});this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=async()=>{document.visibilityState==="visible"&&(await this.refreshFlows(),await this.refreshUserFlowStates(),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,R(t))})}))};this.init(this.config),m()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(m()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=D(this.config);g[t]&&(g[t].onFlowStateChangeHandlers=[])}}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{var e;await this.refreshUserFlowStates(),await this.refreshFlows(),this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(N))&&await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})})(),this.initPromise}async identify(t,e){this.config={...this.config,userId:t},await this.initIfNeeded(),await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),await this.resync()}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.resync()}async track(t,e){if(await this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})}),await this.resync()}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reload(){j(),L(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,R(t))})})}async resync(){this.initPromise=null,await this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,R(t))})})}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}hasFailedToLoad(){return this.hasFailed}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(!g[t]){let e=this,i={set:function(s,c,r){return s[c]&&s[c].flowState&&(JSON.stringify(s[c].flowState)!==JSON.stringify(r==null?void 0:r.flowState)||JSON.stringify(s[c].stepStates)!==JSON.stringify(r==null?void 0:r.stepStates)||JSON.stringify(s[c].shouldTrigger)!==JSON.stringify(r==null?void 0:r.shouldTrigger))&&e.triggerEventHandlers(s[c]),s[c]=r,!0}};if(g[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockUserFlowStates(t);return}g[t].refreshUserFlowStates=async()=>{if(this.config.__readOnly)return;let s=await this.fetch(`/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`:""}`);s&&s.data?(s.data.forEach(r=>{let y=!1,S=g[t].userFlowStates[r.flowId];S&&S.shouldTrigger==!1&&r.shouldTrigger==!0&&(y=!0),g[t].userFlowStates[r.flowId]=r,y&&this.flows.forEach(T=>{T.id==r.flowId&&(T.reload(),this.triggerEventHandlers(g[t].userFlowStates[T.id]))})}),this.hasFailed=!1):this.hasFailed=!0}}await g[t].refreshUserFlowStates()}async refreshFlows(){if(this.flows=[],this.config.__flowConfigOverrides){this.mockFlowConfigs();return}let t=await this.fetch("/flows");t&&t.data?t.data.forEach(i=>{this.flows.push(new F(this.config,i)),this.getGlobalState().previousFlows.set(i.slug,R(this.flows[this.flows.length-1]))}):this.hasFailed=!0}mockFlowConfigs(){Object.keys(this.config.__flowConfigOverrides).forEach(t=>{this.flows.push(new F(this.config,{id:-1,name:"",description:"",data:this.config.__flowConfigOverrides[t],createdAt:new Date().toISOString(),modifiedAt:new Date().toISOString(),slug:t,targetingLogic:"",type:"CHECKLIST",triggerType:"MANUAL",status:"ACTIVE",version:1,active:!0}))})}mockUserFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var s;let i=JSON.parse(this.config.__flowConfigOverrides[e]);g[t].userFlowStates[e]={flowId:e,flowState:"NOT_STARTED_FLOW",lastStepId:null,userId:this.config.userId,foreignUserId:this.config.userId,stepStates:((s=i==null?void 0:i.steps)==null?void 0:s.reduce((c,r)=>(c[r.id]={stepId:r.id,flowSlug:e,actionType:"NOT_STARTED_STEP",createdAt:new Date().toISOString(),blocked:!1,hidden:!1},c),{}))??{},shouldTrigger:!1}})}async triggerEventHandlers(t){t&&this.flows.forEach(e=>{e.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(i=>{let s=this.getGlobalState().previousFlows.get(e.id);i(e,s),this.getGlobalState().previousFlows.set(e.id,R(e))})})}};export{F as Flow,x 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.20'\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'\nexport const 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 let response\n try {\n response = fetch(url, options)\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 if (response.status === 204 || response.status === 201) {\n return getEmptyResponse()\n }\n\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\nexport function 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, getEmptyResponse, 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 /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n /**\n * @ignore\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 NOT_STARTED_STEP,\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's ID.\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object.\n * @ignore\n */\n public configYmlAsJson: any\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The metadata of the Flow.\n * @ignore\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 * @ignore\n */\n private readonly flowDataRaw: FlowDataRaw\n /**\n * @ignore\n */\n private userFlowStateRaw?: UserFlowState\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n /**\n * @ignore\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 /**\n * Reload the Flow data from the server\n */\n reload() {\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * @ignore\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 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 if (this.flowDataRaw.active === false) {\n this.isVisible = false\n }\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 lastActionAt: userFlowStateStep.lastActionAt\n ? new Date(userFlowStateStep.lastActionAt)\n : undefined,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.isStarted) {\n return\n }\n\n thisStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[thisStep.id].actionType = STARTED_STEP\n copy.stepStates[thisStep.id].lastActionAt = new Date().toISOString()\n copy.lastStepId = thisStep.id\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n if (!thisStep.isCompleted) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = new Date()\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (thisStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n thisStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[thisStep.id].actionType = COMPLETED_STEP\n copy.stepStates[thisStep.id].lastActionAt = new Date().toISOString()\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 copy.stepStates[nextStepId].actionType = STARTED_STEP\n const lastAction = new Date()\n copy.stepStates[nextStepId].lastActionAt = lastAction.toISOString()\n this.steps.get(nextStepId).isStarted = true\n this.steps.get(nextStepId).lastActionAt = lastAction\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 foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = new Date()\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.isCompleted) {\n return\n }\n\n thisStep.isCompleted = false\n thisStep.isStarted = false\n thisStep.lastActionAt = undefined\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[thisStep.id].actionType = NOT_STARTED_STEP\n copy.stepStates[thisStep.id].lastActionAt = undefined\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 foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = undefined\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 thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.isCompleted !== previousStep?.isCompleted ||\n thisStep.isStarted !== previousStep?.isStarted ||\n thisStep.isHidden !== previousStep?.isHidden ||\n thisStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\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 * 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 foreignUserGroupId: this.config.groupId,\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 * 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 foreignUserGroupId: this.config.groupId,\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 /**\n * @ignore\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 * 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 foreignUserGroupId: this.config.groupId,\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 * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: Record<string | number, any>) {\n const nextStep = this.getStepByIndex(this.getCurrentStepIndex() + 1)\n if (nextStep) {\n await nextStep.start(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: Record<string | number, any>) {\n const previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\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 * Gets current step\n */\n public getCurrentStep(): FlowStep {\n let maybeCurrentStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false && this.steps.get(key).isHidden === false\n )\n Array.from(this.steps.keys()).forEach((key) => {\n if (\n this.steps.get(key).isStarted &&\n this.steps.get(key).lastActionAt &&\n this.steps.get(key).lastActionAt >\n (this.steps.get(maybeCurrentStepId)?.lastActionAt ?? new Date(0))\n ) {\n maybeCurrentStepId = key\n }\n })\n\n const currentStepId = maybeCurrentStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\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 /**\n * @ignore\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 /**\n * @ignore\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 /**\n * @ignore\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 /**\n * @ignore\n */\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { clearCache, cloneFlow, GUEST_PREFIX, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { FlowDataRaw, FlowStatus, FlowType, TriggerType } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshFlows()\n await this.refreshUserFlowStates()\n }\n }\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n }\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\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 if (this.config.userId && !this.config.userId?.startsWith(GUEST_PREFIX)) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n }),\n })\n }\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { ...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.resync()\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = groupId\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.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n } else if (this.config.userId) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\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 private async resync() {\n this.initPromise = null\n await this.init(this.config)\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 /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @param handler\n */\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\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 /**\n * @ignore\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 /**\n * @ignore\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\n if (this.config.__readOnly && this.config.__flowConfigOverrides) {\n this.mockUserFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n if (this.config.__readOnly) {\n return\n }\n\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${\n this.config.groupId\n ? `&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`\n : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n let shouldReload = false\n const before = frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId]\n\n // Special case: for flows that show up based on targeting logic/rules, we need to check if the flow should be triggered\n if (before && before.shouldTrigger == false && userFlowState.shouldTrigger == true) {\n shouldReload = true\n }\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n if (shouldReload) {\n this.flows.forEach((flow) => {\n if (flow.id == userFlowState.flowId) {\n flow.reload()\n this.triggerEventHandlers(\n frigadeGlobalState[globalStateKey].userFlowStates[flow.id]\n )\n }\n })\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n /**\n * @ignore\n */\n private async refreshFlows() {\n this.flows = []\n\n if (this.config.__flowConfigOverrides) {\n this.mockFlowConfigs()\n return\n }\n\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 } else {\n this.hasFailed = true\n }\n }\n\n /**\n * @ignore\n */\n private mockFlowConfigs() {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n this.flows.push(\n new Flow(this.config, {\n id: -1,\n name: '',\n description: '',\n data: this.config.__flowConfigOverrides[flowId],\n createdAt: new Date().toISOString(),\n modifiedAt: new Date().toISOString(),\n slug: flowId,\n targetingLogic: '',\n type: FlowType.CHECKLIST,\n triggerType: TriggerType.MANUAL,\n status: FlowStatus.ACTIVE,\n version: 1,\n active: true,\n })\n )\n })\n }\n\n /**\n * @ignore\n */\n private mockUserFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n const parsed = JSON.parse(this.config.__flowConfigOverrides[flowId])\n frigadeGlobalState[globalStateKey].userFlowStates[flowId] = {\n flowId,\n flowState: 'NOT_STARTED_FLOW',\n lastStepId: null,\n userId: this.config.userId,\n foreignUserId: this.config.userId,\n stepStates:\n parsed?.steps?.reduce((acc, step) => {\n acc[step.id] = {\n stepId: step.id,\n flowSlug: flowId,\n actionType: 'NOT_STARTED_STEP',\n createdAt: new Date().toISOString(),\n blocked: false,\n hidden: false,\n }\n return acc\n }, {}) ?? {},\n shouldTrigger: false,\n }\n })\n }\n\n /**\n * @ignore\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","getEmptyResponse","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","thisStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","lastAction","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","h","nextStep","NOT_STARTED_FLOW","maybeCurrentStepId","key","_a","currentStepId","currentStep","previousFlow","variables","replaceVariables","str","matches","match","variable","NOT_STARTED_STEP","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","POST_CACHE_TTL_MS","LOCAL_STORAGE_PREFIX","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","clearCache","frigadeGlobalState","key","GET_CACHE_PREFIX","resetAllLocalStorage","isWeb","LOCAL_STORAGE_PREFIX","gracefulFetch","url","options","lastCallAtKey","LAST_POST_CALL_AT","lastCallDataKey","LAST_POST_CALL_DATA","lastCall","getLocalStorage","lastCallData","lastCallDate","POST_CACHE_TTL_MS","getEmptyResponse","setLocalStorage","response","fetch","error","body","e","generateGuestId","guestId","GUEST_KEY","GUEST_PREFIX","uuidv4","isWeb","Frigade","Fetchable","apiKey","config","isWeb","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","groupId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","that","validator","target","key","value","userFlowStatesRaw","userFlowState","shouldReload","before","flowDataRaw","flowData","Flow","parsed","acc","step","previousUserFlowState"]}
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.20'\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'\nexport const 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 let response\n try {\n response = fetch(url, options)\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 if (response.status === 204 || response.status === 201) {\n return getEmptyResponse()\n }\n\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\nexport function 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, getEmptyResponse, 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 /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n /**\n * @ignore\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 NOT_STARTED_STEP,\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's ID.\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object.\n * @ignore\n */\n public configYmlAsJson: any\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The metadata of the Flow.\n * @ignore\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 * @ignore\n */\n private readonly flowDataRaw: FlowDataRaw\n /**\n * @ignore\n */\n private userFlowStateRaw?: UserFlowState\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n /**\n * @ignore\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 /**\n * Reload the Flow data from the server\n */\n reload() {\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * @ignore\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 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 if (this.flowDataRaw.active === false) {\n this.isVisible = false\n }\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 lastActionAt: userFlowStateStep.lastActionAt\n ? new Date(userFlowStateStep.lastActionAt)\n : undefined,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.isStarted) {\n return\n }\n\n thisStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[thisStep.id].actionType = STARTED_STEP\n copy.stepStates[thisStep.id].lastActionAt = new Date().toISOString()\n copy.lastStepId = thisStep.id\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n if (!thisStep.isCompleted) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = new Date()\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (thisStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n thisStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[thisStep.id].actionType = COMPLETED_STEP\n copy.stepStates[thisStep.id].lastActionAt = new Date().toISOString()\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 copy.stepStates[nextStepId].actionType = STARTED_STEP\n const lastAction = new Date()\n copy.stepStates[nextStepId].lastActionAt = lastAction.toISOString()\n this.steps.get(nextStepId).isStarted = true\n this.steps.get(nextStepId).lastActionAt = lastAction\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 foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = new Date()\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.isCompleted) {\n return\n }\n\n thisStep.isCompleted = false\n thisStep.isStarted = false\n thisStep.lastActionAt = undefined\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[thisStep.id].actionType = NOT_STARTED_STEP\n copy.stepStates[thisStep.id].lastActionAt = undefined\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 foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: thisStep.id,\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n thisStep.isCompleted =\n updatedUserFlowState.stepStates[thisStep.id].actionType == COMPLETED_STEP\n thisStep.isStarted = updatedUserFlowState.stepStates[thisStep.id].actionType == STARTED_STEP\n thisStep.lastActionAt = undefined\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 thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.isCompleted !== previousStep?.isCompleted ||\n thisStep.isStarted !== previousStep?.isStarted ||\n thisStep.isHidden !== previousStep?.isHidden ||\n thisStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\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 * 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 foreignUserGroupId: this.config.groupId,\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 * 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 foreignUserGroupId: this.config.groupId,\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 /**\n * @ignore\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 * 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 foreignUserGroupId: this.config.groupId,\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 * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: Record<string | number, any>) {\n const nextStep = this.getStepByIndex(this.getCurrentStepIndex() + 1)\n if (nextStep) {\n await nextStep.start(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: Record<string | number, any>) {\n const previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\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 * Gets current step\n */\n public getCurrentStep(): FlowStep {\n let maybeCurrentStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false && this.steps.get(key).isHidden === false\n )\n Array.from(this.steps.keys()).forEach((key) => {\n if (\n this.steps.get(key).isStarted &&\n this.steps.get(key).lastActionAt &&\n this.steps.get(key).lastActionAt >\n (this.steps.get(maybeCurrentStepId)?.lastActionAt ?? new Date(0))\n ) {\n maybeCurrentStepId = key\n }\n })\n\n const currentStepId = maybeCurrentStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\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 /**\n * @ignore\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 /**\n * @ignore\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 /**\n * @ignore\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 /**\n * @ignore\n */\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { clearCache, cloneFlow, GUEST_PREFIX, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { FlowDataRaw, FlowStatus, FlowType, TriggerType } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshFlows()\n await this.refreshUserFlowStates()\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\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n }\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\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 if (this.config.userId && !this.config.userId?.startsWith(GUEST_PREFIX)) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n }),\n })\n }\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { ...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.resync()\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = groupId\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.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n } else if (this.config.userId) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\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 private async resync() {\n this.initPromise = null\n await this.init(this.config)\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 /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @param handler\n */\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\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 /**\n * @ignore\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 /**\n * @ignore\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\n if (this.config.__readOnly && this.config.__flowConfigOverrides) {\n this.mockUserFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n if (this.config.__readOnly) {\n return\n }\n\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${\n this.config.groupId\n ? `&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`\n : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n let shouldReload = false\n const before = frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId]\n\n // Special case: for flows that show up based on targeting logic/rules, we need to check if the flow should be triggered\n if (before && before.shouldTrigger == false && userFlowState.shouldTrigger == true) {\n shouldReload = true\n }\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n if (shouldReload) {\n this.flows.forEach((flow) => {\n if (flow.id == userFlowState.flowId) {\n flow.reload()\n this.triggerEventHandlers(\n frigadeGlobalState[globalStateKey].userFlowStates[flow.id]\n )\n }\n })\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n /**\n * @ignore\n */\n private async refreshFlows() {\n this.flows = []\n\n if (this.config.__flowConfigOverrides) {\n this.mockFlowConfigs()\n return\n }\n\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 } else {\n this.hasFailed = true\n }\n }\n\n /**\n * @ignore\n */\n private mockFlowConfigs() {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n this.flows.push(\n new Flow(this.config, {\n id: -1,\n name: '',\n description: '',\n data: this.config.__flowConfigOverrides[flowId],\n createdAt: new Date().toISOString(),\n modifiedAt: new Date().toISOString(),\n slug: flowId,\n targetingLogic: '',\n type: FlowType.CHECKLIST,\n triggerType: TriggerType.MANUAL,\n status: FlowStatus.ACTIVE,\n version: 1,\n active: true,\n })\n )\n })\n }\n\n /**\n * @ignore\n */\n private mockUserFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n const parsed = JSON.parse(this.config.__flowConfigOverrides[flowId])\n frigadeGlobalState[globalStateKey].userFlowStates[flowId] = {\n flowId,\n flowState: 'NOT_STARTED_FLOW',\n lastStepId: null,\n userId: this.config.userId,\n foreignUserId: this.config.userId,\n stepStates:\n parsed?.steps?.reduce((acc, step) => {\n acc[step.id] = {\n stepId: step.id,\n flowSlug: flowId,\n actionType: 'NOT_STARTED_STEP',\n createdAt: new Date().toISOString(),\n blocked: false,\n hidden: false,\n }\n return acc\n }, {}) ?? {},\n shouldTrigger: false,\n }\n })\n }\n\n /**\n * @ignore\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","getEmptyResponse","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","thisStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","lastAction","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","nextStep","NOT_STARTED_FLOW","maybeCurrentStepId","key","_a","currentStepId","currentStep","previousFlow","h","variables","replaceVariables","str","matches","match","variable","NOT_STARTED_STEP","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","POST_CACHE_TTL_MS","LOCAL_STORAGE_PREFIX","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","clearCache","frigadeGlobalState","key","GET_CACHE_PREFIX","resetAllLocalStorage","isWeb","LOCAL_STORAGE_PREFIX","gracefulFetch","url","options","lastCallAtKey","LAST_POST_CALL_AT","lastCallDataKey","LAST_POST_CALL_DATA","lastCall","getLocalStorage","lastCallData","lastCallDate","POST_CACHE_TTL_MS","getEmptyResponse","setLocalStorage","response","fetch","error","body","e","generateGuestId","guestId","GUEST_KEY","GUEST_PREFIX","uuidv4","isWeb","Frigade","Fetchable","apiKey","config","flow","handler","lastFlow","cloneFlow","isWeb","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","groupId","event","flowId","resetAllLocalStorage","clearCache","h","that","validator","target","key","value","userFlowStatesRaw","userFlowState","shouldReload","before","flowDataRaw","flowData","Flow","parsed","acc","step","previousUserFlowState"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frigade/js",
3
- "version": "0.2.24",
3
+ "version": "0.2.25",
4
4
  "description": "The official Javascript SDK for Frigade.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",