@frigade/js 0.1.3 → 0.2.0

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/README.md CHANGED
@@ -78,7 +78,7 @@ await flow.complete()
78
78
 
79
79
  ```js
80
80
  const flow = await frigade.getFlow('FLOW_ID')
81
- const step = flow.steps['STEP_ID']
81
+ const step = flow.steps.get('STEP_ID')
82
82
  await step.start()
83
83
  await step.complete()
84
84
  ```
@@ -92,6 +92,43 @@ await frigade.track('EVENT_NAME', {
92
92
  })
93
93
  ```
94
94
 
95
+ #### Event handlers
96
+ Global event handlers can be registered to be notified when any state change occurs in any flow. For example, to be notified when a flow is completed:
97
+
98
+ ```js
99
+ // This callback will be called when a the current user/group changes state in any flow
100
+ const callback = (updatedFlow, previousFlow) => {
101
+ console.log('Flow state changed:', flow.isCompleted)
102
+ console.log('Step state changed:', flow.steps.get('STEP_ID').isCompleted)
103
+ };
104
+
105
+ frigade.onStateChange(callback);
106
+ // To remove the callback use:
107
+ frigade.removeOnFlowStateChangeHandler(callback);
108
+ ```
109
+ Flow specific event handlers can be registered to be notified when a specific flow changes state. For example, to be notified when a flow is completed:
110
+
111
+ ```js
112
+ // This callback will be called when a the current user/group changes state in the flow with id FLOW_ID
113
+ const flow = await frigade.getFlow('FLOW_ID')
114
+ const callback = (updatedFlow, previousFlow) => {
115
+ console.log('Flow state changed:', flow.isCompleted)
116
+ console.log('Step state changed:', flow.steps.get('STEP_ID').isCompleted)
117
+ };
118
+ flow.onStateChange(callback);
119
+ ```
120
+ To only target a specific step in a flow, use:
121
+ ```js
122
+ // This callback will be called when a the current user/group changes state in the flow with id FLOW_ID and step with id STEP_ID
123
+ const flow = await frigade.getFlow('FLOW_ID')
124
+ const step = flow.steps.get('STEP_ID')
125
+ const callback = (updatedStep, previousStep) => {
126
+ console.log('Step state changed:', step.isCompleted)
127
+ };
128
+ step.onStateChange(callback);
129
+ ```
130
+
131
+
95
132
  ## Cross-platform support
96
133
 
97
134
  All non-UI related functionality of the SDK works in all JavaScript environments (Node.js, browser, React Native, etc.).
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- var k=Object.create;var I=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,B=Object.prototype.hasOwnProperty;var X=(e,s)=>{for(var t in s)I(e,t,{get:s[t],enumerable:!0})},N=(e,s,t,i)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of V(s))!B.call(e,r)&&r!==t&&I(e,r,{get:()=>s[r],enumerable:!(i=z(s,r))||i.enumerable});return e};var Y=(e,s,t)=>(t=e!=null?k(j(e)):{},N(s||!e||!e.__esModule?I(t,"default",{value:e,enumerable:!0}):t,e)),q=e=>N(I({},"__esModule",{value:!0}),e);var et={};X(et,{Flow:()=>f,Frigade:()=>E});module.exports=q(et);var L="0.1.3";var J=Y(require("cross-fetch"),1),G=require("uuid");var u="COMPLETED_FLOW",U="SKIPPED_FLOW",F="STARTED_FLOW",W="NOT_STARTED_FLOW",S="COMPLETED_STEP",h="STARTED_STEP",Q="frigade-last-call-at-",Z="frigade-last-call-data-",x="frigade-guest-key",tt="guest_";function m(e){return JSON.parse(JSON.stringify(e))}function K(e){return{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","X-Frigade-SDK-Version":L,"X-Frigade-SDK-Platform":"Javascript"}}}function _(e){return window&&window.localStorage?window.localStorage.getItem(e):null}function M(e,s){window&&window.localStorage&&window.localStorage.setItem(e,s)}function $(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(e=>{e.startsWith("frigade-")&&window.localStorage.removeItem(e)})}async function H(e,s){let t=Q+e,i=Z+e;if(window&&window.localStorage&&s&&s.body&&s.method==="POST"){let o=_(t),l=_(i);if(o&&l&&l==s.body){let c=new Date(o);if(new Date().getTime()-c.getTime()<1e3)return O()}M(t,new Date().toISOString()),M(i,s.body)}let r;try{r=await(0,J.default)(e,s)}catch(o){return O(o)}return r?r.staus>=400?O(r.statusText):r.json():O()}function O(e){return e&&console.log("Call to Frigade failed",e),{json:()=>({})}}function D(){if(typeof window<"u"&&typeof window.localStorage<"u"){let e=_(x);return e||(e=`${tt}${(0,G.v4)()}`,window.localStorage.setItem(x,e)),e}}var n={};function d(e){return`${e.__instanceId}-${e.apiKey}:${e.userId??""}:${e.organizationId??""}`}var w=class{constructor(s){this.config={apiKey:"",apiUrl:"//api.frigade.com/v1/public",userId:D(),__instanceId:Math.random().toString(36).substring(7)};this.config={...this.config,...s}}async fetch(s,t){return H(`${this.config.apiUrl}${s}`,{...t??{},...K(this.config.apiKey)})}};var f=class extends w{constructor(t,i){super(t);this.isVisible=!1;this.nonce=Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15);this.flowDataRaw=i,this.initFromRawData(i)}initFromRawData(t){let i=JSON.parse(t.data),r=i.steps??i.data??[];this.id=t.slug,this.metadata=t,this.rawData=i,this.title=this.rawData.title,this.subtitle=this.rawData.subtitle;let o=this.getUserFlowState();this.isCompleted=o.flowState==u,this.isStarted=o.flowState==F,this.isSkipped=o.flowState==U;let l=this.isCompleted||this.isSkipped,c=t.targetingLogic&&o.shouldTrigger===!1;this.isVisible=!l&&!c,this.steps=new Map,r.forEach((p,C)=>{let y=o.stepStates[p.id],R={...p,isCompleted:y.actionType==S,isStarted:y.actionType==h,isHidden:y.hidden,isBlocked:y.blocked,order:C};R.start=async P=>{let a=this.steps.get(p.id);if(a.isStarted||a.isCompleted)return;a.isStarted=!0;let T=m(n[d(this.config)].userFlowStates[this.id]);T.stepStates[a.id].actionType=h,T.lastStepId=a.id,n[d(this.config)].userFlowStates[this.id]=T,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:a.id,data:P??{},createdAt:new Date().toISOString(),actionType:h})}),await this.refreshUserFlowState();let g=this.getUserFlowState();a.isCompleted=g.stepStates[a.id].actionType==S,a.isStarted=g.stepStates[a.id].actionType==h},R.complete=async P=>{let a=this.steps.get(p.id);if(a.isCompleted)return;let g=this.getNumberOfCompletedSteps()+1==this.steps.size;a.isCompleted=!0,this.isStarted=!0;let b=m(n[d(this.config)].userFlowStates[this.id]);b.stepStates[a.id].actionType=S,b.flowState=g?u:F;let v=Array.from(this.steps.keys())[C+1];v&&(b.lastStepId=v),g&&this.optimisticallyMarkFlowCompleted(),n[d(this.config)].userFlowStates[this.id]=b,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:a.id,data:P??{},createdAt:new Date().toISOString(),actionType:S})}),g?await this.complete():await this.refreshUserFlowState();let A=this.getUserFlowState();a.isCompleted=A.stepStates[a.id].actionType==S,a.isStarted=A.stepStates[a.id].actionType==h},this.steps.set(p.id,R)})}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let i=m(n[d(this.config)].userFlowStates[this.id]);i.flowState=F,n[d(this.config)].userFlowStates[this.id]=i,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:F})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:u})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=m(n[d(this.config)].userFlowStates[this.id]);t.flowState=u,n[d(this.config)].userFlowStates[this.id]=t,this.isVisible=!1}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:U})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,n[d(this.config)].userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:W})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let i=Array.from(this.steps.keys()).find(r=>this.steps.get(r).isCompleted===!1)??Array.from(this.steps.keys())[0];return this.steps.get(i)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getUserFlowState(){return n[d(this.config)].userFlowStates[this.id]}async refreshUserFlowState(){await n[d(this.config)].refreshUserFlowStates()}};var E=class extends w{constructor(t,i){super({apiKey:t,...i});this.flows=[];this.onFlowStateChangeHandlers=[];this.previousFlows=new Map;this.init(this.config)}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,i){await this.initIfNeeded(),this.config.userId=t,await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:i})}),await this.refreshUserFlowStates()}async group(t,i){await this.initIfNeeded(),this.config.organizationId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,properties:i})}),await this.refreshUserFlowStates()}async track(t,i){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,event:t,properties:i})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(i=>i.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){$(),this.config.userId=D(),this.config.organizationId=void 0}onFlowStateChange(t){this.onFlowStateChangeHandlers.push(t)}removeOnFlowStateChangeHandler(t){this.onFlowStateChangeHandlers=this.onFlowStateChangeHandlers.filter(i=>i!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=d(this.config);if(!n[t]){let i=this,r={set:function(o,l,c){return o[l]&&o[l].flowState&&(JSON.stringify(o[l].flowState)!==JSON.stringify(c.flowState)||JSON.stringify(o[l].stepStates)!==JSON.stringify(c.stepStates)||JSON.stringify(o[l].shouldTrigger)!==JSON.stringify(c.shouldTrigger))&&i.triggerEventHandlers(o[l]),o[l]=c,!0}};n[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},r)},n[t].refreshUserFlowStates=async()=>{let o=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.organizationId?`&foreignUserGroupId=${this.config.organizationId}`:""}`);o&&o.data&&o.data.forEach(c=>{n[t].userFlowStates[c.flowId]=c})}}await n[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(r=>{this.flows.push(new f(this.config,r))})}async triggerEventHandlers(t){t&&this.flows.forEach(i=>{i.nonce=Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15),i.id==t.flowId&&this.onFlowStateChangeHandlers.forEach(r=>{let o=this.previousFlows.get(r),l=o?o.get(i.id):void 0;r(i,l),o||this.previousFlows.set(r,new Map),this.previousFlows.get(r).set(i.id,i)})})}};0&&(module.exports={Flow,Frigade});
2
+ var V=Object.create;var I=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,X=Object.prototype.hasOwnProperty;var q=(e,s)=>{for(var t in s)I(e,t,{get:s[t],enumerable:!0})},L=(e,s,t,i)=>{if(s&&typeof s=="object"||typeof s=="function")for(let o of Y(s))!X.call(e,o)&&o!==t&&I(e,o,{get:()=>s[o],enumerable:!(i=B(s,o))||i.enumerable});return e};var Q=(e,s,t)=>(t=e!=null?V(j(e)):{},L(s||!e||!e.__esModule?I(t,"default",{value:e,enumerable:!0}):t,e)),Z=e=>L(I({},"__esModule",{value:!0}),e);var st={};q(st,{Flow:()=>w,Frigade:()=>P});module.exports=Z(st);var H="0.2.0";var K=Q(require("cross-fetch"),1),$=require("uuid");var c={};function O(e){return`${e.__instanceId}-${e.apiKey}:${e.userId??""}:${e.organizationId??""}`}var u=class{constructor(s){this.config={apiKey:"",apiUrl:"//api.frigade.com/v1/public",userId:E(),__instanceId:Math.random().toString(36).substring(7)};this.config={...this.config,...s}}async fetch(s,t){return J(`${this.config.apiUrl}${s}`,{...t??{},...x(this.config.apiKey)})}getGlobalState(){let s=O(this.config);if(!c[s])throw new Error("Frigade not initialized");return c[s]}};var w=class extends u{constructor(t,i){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.flowDataRaw=i,this.initFromRawData(i)}initFromRawData(t){let i=JSON.parse(t.data),o=i.steps??i.data??[];this.id=t.slug,this.rawData=t,this.configYmlAsJson=i,this.title=this.configYmlAsJson.title,this.subtitle=this.configYmlAsJson.subtitle;let a=this.getUserFlowState();this.isCompleted=a.flowState==b,this.isStarted=a.flowState==T,this.isSkipped=a.flowState==U;let d=this.isCompleted||this.isSkipped,p=t.targetingLogic&&a.shouldTrigger===!1;this.isVisible=!d&&!p;let R=new Map;o.forEach((h,v)=>{let C=a.stepStates[h.id],y={...h,isCompleted:C.actionType==F,isStarted:C.actionType==m,isHidden:C.hidden,isBlocked:C.blocked,order:v};y.start=async S=>{let r=this.steps.get(h.id);if(r.isStarted||r.isCompleted)return;r.isStarted=!0;let g=f(this.getGlobalState().userFlowStates[this.id]);g.stepStates[r.id].actionType=m,g.lastStepId=r.id,this.getGlobalState().userFlowStates[this.id]=g,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:r.id,data:S??{},createdAt:new Date().toISOString(),actionType:m})}),await this.refreshUserFlowState();let l=this.getUserFlowState();r.isCompleted=l.stepStates[r.id].actionType==F,r.isStarted=l.stepStates[r.id].actionType==m},y.complete=async S=>{let r=this.steps.get(h.id);if(r.isCompleted)return;let l=this.getNumberOfCompletedSteps()+1==this.steps.size;r.isCompleted=!0,this.isStarted=!0;let n=f(this.getGlobalState().userFlowStates[this.id]);n.stepStates[r.id].actionType=F,n.flowState=l?b:T;let A=Array.from(this.steps.keys())[v+1];A&&(n.lastStepId=A),l&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=n,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:r.id,data:S??{},createdAt:new Date().toISOString(),actionType:F})}),l?await this.complete():await this.refreshUserFlowState();let N=this.getUserFlowState();r.isCompleted=N.stepStates[r.id].actionType==F,r.isStarted=N.stepStates[r.id].actionType==m},y.onStateChange=S=>{let r=g=>{if(g.id!==this.id)return;let l=g.steps.get(h.id),n=this.lastStepUpdate.get(S);(l.isCompleted!==(n==null?void 0:n.isCompleted)||l.isStarted!==(n==null?void 0:n.isStarted)||l.isHidden!==(n==null?void 0:n.isHidden)||l.isBlocked!==(n==null?void 0:n.isBlocked))&&(S(l,n??f(l)),this.lastStepUpdate.set(S,f(l)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(S,r),this.getGlobalState().onFlowStateChangeHandlers.push(r)},y.removeStateChangeHandler=S=>{let r=this.getGlobalState().onStepStateChangeHandlerWrappers.get(S);r&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(g=>g!==r))},R.set(h.id,y)}),this.steps=R}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let i=f(this.getGlobalState().userFlowStates[this.id]);i.flowState=T,this.getGlobalState().userFlowStates[this.id]=i,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:T})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=f(this.getGlobalState().userFlowStates[this.id]);t.flowState=b,this.getGlobalState().userFlowStates[this.id]=t,this.isVisible=!1}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:U})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,this.getGlobalState().userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:W})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let i=Array.from(this.steps.keys()).find(o=>this.steps.get(o).isCompleted===!1)??Array.from(this.steps.keys())[0];return this.steps.get(i)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}onStateChange(t){let i=(o,a)=>{(o.id===this.id&&(o.isCompleted!==a.isCompleted||o.isStarted!==a.isStarted||o.isSkipped!==a.isSkipped||o.isVisible!==a.isVisible)||JSON.stringify(o.steps)!==JSON.stringify(a.steps))&&t(o,a)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,i),this.getGlobalState().onFlowStateChangeHandlers.push(i)}removeStateChangeHandler(t){let i=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);i&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(o=>o!==i))}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var b="COMPLETED_FLOW",U="SKIPPED_FLOW",T="STARTED_FLOW",W="NOT_STARTED_FLOW",F="COMPLETED_STEP",m="STARTED_STEP",tt="frigade-last-call-at-",et="frigade-last-call-data-",M="frigade-guest-key",it="guest_";function G(e){let s=new w(e.config,e.rawData);return s.isCompleted=e.isCompleted,s.isStarted=e.isStarted,s.isSkipped=e.isSkipped,s.isVisible=e.isVisible,s.steps=e.steps,s}function f(e){return JSON.parse(JSON.stringify(e))}function x(e){return{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","X-Frigade-SDK-Version":H,"X-Frigade-SDK-Platform":"Javascript"}}}function _(e){return window&&window.localStorage?window.localStorage.getItem(e):null}function k(e,s){window&&window.localStorage&&window.localStorage.setItem(e,s)}function z(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(e=>{e.startsWith("frigade-")&&window.localStorage.removeItem(e)})}async function J(e,s){let t=tt+e,i=et+e;if(window&&window.localStorage&&s&&s.body&&s.method==="POST"){let a=_(t),d=_(i);if(a&&d&&d==s.body){let p=new Date(a);if(new Date().getTime()-p.getTime()<1e3)return D()}k(t,new Date().toISOString()),k(i,s.body)}let o;try{o=await(0,K.default)(e,s)}catch(a){return D(a)}return o?o.staus>=400?D(o.statusText):o.json():D()}function D(e){return e&&console.log("Call to Frigade failed",e),{json:()=>({})}}function E(){if(typeof window<"u"&&typeof window.localStorage<"u"){let e=_(M);return e||(e=`${it}${(0,$.v4)()}`,window.localStorage.setItem(M,e)),e}}var P=class extends u{constructor(t,i){super({apiKey:t,...i});this.flows=[];this.init(this.config)}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,i){await this.initIfNeeded(),this.config.userId=t,await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:i})}),await this.refreshUserFlowStates()}async group(t,i){await this.initIfNeeded(),this.config.organizationId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,properties:i})}),await this.refreshUserFlowStates()}async track(t,i){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,event:t,properties:i})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(i=>i.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){z(),this.config.userId=E(),this.config.organizationId=void 0}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}removeStateChangeHandler(t){this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(i=>i!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=O(this.config);if(!c[t]){let i=this,o={set:function(a,d,p){return a[d]&&a[d].flowState&&(JSON.stringify(a[d].flowState)!==JSON.stringify(p.flowState)||JSON.stringify(a[d].stepStates)!==JSON.stringify(p.stepStates)||JSON.stringify(a[d].shouldTrigger)!==JSON.stringify(p.shouldTrigger))&&i.triggerEventHandlers(a[d]),a[d]=p,!0}};c[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},o),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},c[t].refreshUserFlowStates=async()=>{let a=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.organizationId?`&foreignUserGroupId=${this.config.organizationId}`:""}`);a&&a.data&&a.data.forEach(p=>{c[t].userFlowStates[p.flowId]=p})}}await c[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(o=>{this.flows.push(new w(this.config,o)),this.getGlobalState().previousFlows.set(o.slug,G(this.flows[this.flows.length-1]))})}async triggerEventHandlers(t){t&&this.flows.forEach(i=>{i.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(o=>{let a=this.getGlobalState().previousFlows.get(i.id);o(i,a),this.getGlobalState().previousFlows.set(i.id,G(i))})})}};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'\nimport Flow from './core/flow'\n\nexport { Flow }\n\nexport * from './types'\n","export const VERSION_NUMBER = '0.1.3'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\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 (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\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 (window && window.localStorage && 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 < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(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","import { FrigadeConfig, UserFlowState } from '../types'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\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.organizationId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: '//api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n this.config = {\n ...this.config,\n ...config,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport default class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public rawData: Record<any, any>\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public metadata: 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 /**\n * Nonce\n */\n public nonce =\n Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)\n\n private flowDataRaw: FlowDataRaw\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.metadata = flowDataRaw\n this.rawData = flowDataYml\n this.title = this.rawData.title\n this.subtitle = this.rawData.subtitle\n\n const userFlowState = this.getUserFlowState()\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 this.steps = new Map()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const copy = clone(\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id]\n )\n copy.stepStates[currentStep.id].actionType = STARTED_STEP\n copy.lastStepId = currentStep.id\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n currentStep.isCompleted = true\n this.isStarted = true\n const copy = clone(\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id]\n )\n\n copy.stepStates[currentStep.id].actionType = COMPLETED_STEP\n copy.flowState = isLastStep ? COMPLETED_FLOW : STARTED_FLOW\n\n const nextStepId = Array.from(this.steps.keys())[index + 1]\n if (nextStepId) {\n copy.lastStepId = nextStepId\n }\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = copy\n\n // if all steps are now completed, mark flow completed\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n if (isLastStep) {\n await this.complete()\n } else {\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n this.steps.set(step.id, stepObj)\n })\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const copy = clone(frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id])\n copy.flowState = STARTED_FLOW\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n private optimisticallyMarkFlowCompleted() {\n this.isStarted = true\n this.isCompleted = true\n const copy = clone(frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id])\n copy.flowState = COMPLETED_FLOW\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = copy\n this.isVisible = false\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await frigadeGlobalState[getGlobalStateKey(this.config)].refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { generateGuestId, resetAllLocalStorage } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n private onFlowStateChangeHandlers: ((flow: Flow, previousFlow?: Flow) => void)[] = []\n private previousFlows: Map<(flow: Flow, previousFlow: Flow) => void, Map<string, Flow>> =\n new Map()\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.userId = userId\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.organizationId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.config.userId = generateGuestId()\n this.config.organizationId = undefined\n }\n\n public onFlowStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.onFlowStateChangeHandlers.push(handler)\n }\n\n public removeOnFlowStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.onFlowStateChangeHandlers = this.onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n target[key] &&\n target[key].flowState &&\n (JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState) ||\n JSON.stringify(target[key].stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger))\n ) {\n that.triggerEventHandlers(target[key])\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.organizationId ? `&foreignUserGroupId=${this.config.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n })\n }\n }\n\n private async triggerEventHandlers(previousUserFlowState: UserFlowState) {\n if (previousUserFlowState) {\n this.flows.forEach((flow) => {\n flow.nonce =\n Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)\n if (flow.id == previousUserFlowState.flowId) {\n this.onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlows = this.previousFlows.get(handler)\n const lastFlow = lastFlows ? lastFlows.get(flow.id) : undefined\n handler(flow, lastFlow)\n if (!lastFlows) {\n this.previousFlows.set(handler, new Map())\n }\n this.previousFlows.get(handler).set(flow.id, flow)\n })\n }\n })\n }\n }\n}\n"],"mappings":";6iBAAA,IAAAA,GAAA,GAAAC,EAAAD,GAAA,UAAAE,EAAA,YAAAC,IAAA,eAAAC,EAAAJ,ICAO,IAAMK,EAAiB,QCC9B,IAAAC,EAAkB,4BAClBC,EAA6B,gBAGtB,IAAMC,EAAiB,iBACjBC,EAAe,eACfC,EAAe,eACfC,EAAmB,mBACnBC,EAAiB,iBACjBC,EAAe,eAGtBC,EAAoB,wBACpBC,EAAsB,0BACtBC,EAAY,oBACZC,GAAe,SAEd,SAASC,EAASC,EAAW,CAClC,OAAO,KAAK,MAAM,KAAK,UAAUA,CAAG,CAAC,CACvC,CAEO,SAASC,EAAWC,EAAgB,CACzC,MAAO,CACL,QAAS,CACP,cAAe,UAAUA,IACzB,eAAgB,mBAChB,wBAAyBC,EACzB,yBAA0B,YAC5B,CACF,CACF,CAEA,SAASC,EAAgBC,EAAa,CACpC,OAAI,QAAU,OAAO,aACZ,OAAO,aAAa,QAAQA,CAAG,EAEjC,IACT,CAEA,SAASC,EAAgBD,EAAaE,EAAe,CAC/C,QAAU,OAAO,cACnB,OAAO,aAAa,QAAQF,EAAKE,CAAK,CAE1C,CAEO,SAASC,GAAuB,CACjC,QAAU,OAAO,cAEnB,OAAO,KAAK,OAAO,YAAY,EAAE,QAASH,GAAQ,CAC5CA,EAAI,WAAW,UAAU,GAC3B,OAAO,aAAa,WAAWA,CAAG,CAEtC,CAAC,CAEL,CAEA,eAAsBI,EAAcC,EAAaC,EAAc,CAC7D,IAAMC,EAAgBjB,EAAoBe,EACpCG,EAAkBjB,EAAsBc,EAC9C,GAAI,QAAU,OAAO,cAAgBC,GAAWA,EAAQ,MAAQA,EAAQ,SAAW,OAAQ,CACzF,IAAMG,EAAWV,EAAgBQ,CAAa,EACxCG,EAAeX,EAAgBS,CAAe,EACpD,GAAIC,GAAYC,GAAgBA,GAAgBJ,EAAQ,KAAM,CAC5D,IAAMK,EAAe,IAAI,KAAKF,CAAQ,EAItC,GAHY,IAAI,KAAK,EACJ,QAAQ,EAAIE,EAAa,QAAQ,EAEvC,IACT,OAAOC,EAAiB,EAG5BX,EAAgBM,EAAe,IAAI,KAAK,EAAE,YAAY,CAAC,EACvDN,EAAgBO,EAAiBF,EAAQ,IAAI,EAG/C,IAAIO,EACJ,GAAI,CACFA,EAAW,QAAM,EAAAC,SAAMT,EAAKC,CAAO,CACrC,OAASS,EAAP,CACA,OAAOH,EAAiBG,CAAK,CAC/B,CAEA,OAAKF,EAIDA,EAAS,OAAS,IACbD,EAAiBC,EAAS,UAAU,EAGtCA,EAAS,KAAK,EAPZD,EAAiB,CAQ5B,CAEA,SAASA,EAAiBG,EAAa,CACrC,OAAIA,GACF,QAAQ,IAAI,yBAA0BA,CAAK,EAItC,CACL,KAAM,KAAO,CAAC,EAChB,CACF,CAEO,SAASC,GAAkB,CAChC,GAAI,OAAO,OAAW,KAAe,OAAO,OAAO,aAAiB,IAAa,CAC/E,IAAIC,EAAUlB,EAAgBP,CAAS,EACvC,OAAKyB,IACHA,EAAU,GAAGxB,QAAe,EAAAyB,IAAO,IACnC,OAAO,aAAa,QAAQ1B,EAAWyB,CAAO,GAEzCA,EAEX,CC3GO,IAAIE,EAAyD,CAAC,EAE9D,SAASC,EAAkBC,EAAuC,CACvE,MAAO,GAAGA,EAAe,gBAAgBA,EAAe,UAAUA,EAAe,QAAU,MACzFA,EAAe,gBAAkB,IAErC,CCVO,IAAMC,EAAN,KAAgB,CAQrB,YAAYC,EAAuB,CAPnC,KAAO,OAAwB,CAC7B,OAAQ,GACR,OAAQ,8BACR,OAAQC,EAAgB,EACxB,aAAc,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,CACtD,EAGE,KAAK,OAAS,CACZ,GAAG,KAAK,OACR,GAAGD,CACL,CACF,CAEA,MAAa,MAAME,EAAcC,EAA4B,CAC3D,OAAOC,EAAc,GAAG,KAAK,OAAO,SAASF,IAAQ,CACnD,GAAIC,GAAW,CAAC,EAChB,GAAGE,EAAW,KAAK,OAAO,MAAM,CAClC,CAAC,CACH,CACF,ECTA,IAAqBC,EAArB,cAAkCC,CAAU,CAkD1C,YAAYC,EAAuBC,EAA0B,CAC3D,MAAMD,CAAM,EAXd,KAAO,UAAqB,GAK5B,KAAO,MACL,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,EAAE,EAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,EAAE,EAMxF,KAAK,YAAcC,EACnB,KAAK,gBAAgBA,CAAW,CAClC,CAEQ,gBAAgBA,EAA0B,CAChD,IAAMC,EAAc,KAAK,MAAMD,EAAY,IAAI,EACzCE,EAAQD,EAAY,OAASA,EAAY,MAAQ,CAAC,EACxD,KAAK,GAAKD,EAAY,KACtB,KAAK,SAAWA,EAChB,KAAK,QAAUC,EACf,KAAK,MAAQ,KAAK,QAAQ,MAC1B,KAAK,SAAW,KAAK,QAAQ,SAE7B,IAAME,EAAgB,KAAK,iBAAiB,EAE5C,KAAK,YAAcA,EAAc,WAAaC,EAC9C,KAAK,UAAYD,EAAc,WAAaE,EAC5C,KAAK,UAAYF,EAAc,WAAaG,EAC5C,IAAMC,EAAe,KAAK,aAAe,KAAK,UACxCC,EACJR,EAAY,gBAAkBG,EAAc,gBAAkB,GAChE,KAAK,UAAY,CAACI,GAAgB,CAACC,EACnC,KAAK,MAAQ,IAAI,IAEjBN,EAAM,QAAQ,CAACO,EAAMC,IAAU,CAC7B,IAAMC,EAAoBR,EAAc,WAAWM,EAAK,EAAE,EACpDG,EAAU,CACd,GAAGH,EACH,YAAaE,EAAkB,YAAcE,EAC7C,UAAWF,EAAkB,YAAcG,EAC3C,SAAUH,EAAkB,OAC5B,UAAWA,EAAkB,QAC7B,MAAOD,CACT,EAEAE,EAAQ,MAAQ,MAAOG,GAA8C,CACnE,IAAMC,EAAc,KAAK,MAAM,IAAIP,EAAK,EAAE,EAE1C,GAAIO,EAAY,WAAaA,EAAY,YACvC,OAGFA,EAAY,UAAY,GACxB,IAAMC,EAAOC,EACXC,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,CAC3E,EACAH,EAAK,WAAWD,EAAY,EAAE,EAAE,WAAaF,EAC7CG,EAAK,WAAaD,EAAY,GAC9BG,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,EAAIH,EAE7E,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQD,EAAY,GACpB,KAAMD,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYD,CACd,CAAC,CACH,CAAC,EAED,MAAM,KAAK,qBAAqB,EAEhC,IAAMO,EAAuB,KAAK,iBAAiB,EACnDL,EAAY,YACVK,EAAqB,WAAWL,EAAY,EAAE,EAAE,YAAcH,EAChEG,EAAY,UACVK,EAAqB,WAAWL,EAAY,EAAE,EAAE,YAAcF,CAClE,EAEAF,EAAQ,SAAW,MAAOG,GAA8C,CACtE,IAAMC,EAAc,KAAK,MAAM,IAAIP,EAAK,EAAE,EAE1C,GAAIO,EAAY,YACd,OAIF,IAAMM,EADyB,KAAK,0BAA0B,EAClB,GAAK,KAAK,MAAM,KAE5DN,EAAY,YAAc,GAC1B,KAAK,UAAY,GACjB,IAAMC,EAAOC,EACXC,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,CAC3E,EAEAH,EAAK,WAAWD,EAAY,EAAE,EAAE,WAAaH,EAC7CI,EAAK,UAAYK,EAAalB,EAAiBC,EAE/C,IAAMkB,EAAa,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAEb,EAAQ,CAAC,EACtDa,IACFN,EAAK,WAAaM,GAGhBD,GACF,KAAK,gCAAgC,EAGvCH,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,EAAIH,EAG7E,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQD,EAAY,GACpB,KAAMD,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYF,CACd,CAAC,CACH,CAAC,EAEGS,EACF,MAAM,KAAK,SAAS,EAEpB,MAAM,KAAK,qBAAqB,EAGlC,IAAMD,EAAuB,KAAK,iBAAiB,EACnDL,EAAY,YACVK,EAAqB,WAAWL,EAAY,EAAE,EAAE,YAAcH,EAChEG,EAAY,UACVK,EAAqB,WAAWL,EAAY,EAAE,EAAE,YAAcF,CAClE,EAEA,KAAK,MAAM,IAAIL,EAAK,GAAIG,CAAO,CACjC,CAAC,CACH,CAKA,MAAa,MAAMG,EAA2C,CAC5D,GAAI,KAAK,WAAa,KAAK,YACzB,OAGF,KAAK,UAAY,GACjB,IAAME,EAAOC,EAAMC,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,CAAC,EAC7FH,EAAK,UAAYZ,EACjBc,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,EAAIH,EAE7E,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMF,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYV,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,CACvC,CAKA,MAAa,SAASU,EAA2C,CAC3D,KAAK,cAGT,KAAK,gCAAgC,EAErC,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMA,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYX,CACd,CAAC,CACH,CAAC,EAED,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,EACvC,CAEQ,iCAAkC,CACxC,KAAK,UAAY,GACjB,KAAK,YAAc,GACnB,IAAMa,EAAOC,EAAMC,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,CAAC,EAC7FH,EAAK,UAAYb,EACjBe,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,EAAIH,EAC7E,KAAK,UAAY,EACnB,CAKA,MAAa,KAAKF,EAA2C,CAC3D,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,KAAK,eAAe,EAAE,GAC9B,KAAMA,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYT,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,CACvC,CAKA,MAAa,SAAU,CACrB,KAAK,YAAc,GACnB,KAAK,YAAc,GACnBa,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eAAe,KAAK,EAAE,EAAI,KAC7E,MAAM,KAAK,MAAM,iBAAkB,CACjC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,SAAU,KAAK,GACf,OAAQ,UACR,KAAM,CAAC,EACP,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYI,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,CAClC,CAMO,eAAed,EAAqC,CACzD,OAAO,KAAK,MAAM,IAAI,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAEA,CAAK,CAAC,CAC5D,CAKO,gBAA2B,CAKhC,IAAMe,EAJa,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAE,KAC9CC,GAAQ,KAAK,MAAM,IAAIA,CAAG,EAAE,cAAgB,EAC/C,GAEoC,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,EAAE,CAAC,EACnE,OAAO,KAAK,MAAM,IAAID,CAAa,CACrC,CAKO,2BAAoC,CACzC,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,OAAQhB,GAASA,EAAK,WAAW,EAAE,MAC5E,CAEQ,kBAAkC,CAExC,OADuBU,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,eACpD,KAAK,EAAE,CAC/B,CAEA,MAAc,sBAAuB,CACnC,MAAMD,EAAmBC,EAAkB,KAAK,MAAM,CAAC,EAAE,sBAAsB,CACjF,CACF,ECxUO,IAAMO,EAAN,cAAsBC,CAAU,CAOrC,YAAYC,EAAgBC,EAAwB,CAClD,MAAM,CACJ,OAAAD,EACA,GAAGC,CACL,CAAC,EAVH,KAAQ,MAAgB,CAAC,EAEzB,KAAQ,0BAA2E,CAAC,EACpF,KAAQ,cACN,IAAI,IAQJ,KAAK,KAAK,KAAK,MAAM,CACvB,CAEA,MAAc,KAAKA,EAAsC,CACvD,YAAK,OAAS,CACZ,GAAG,KAAK,OACR,GAAGA,CACL,EAEA,KAAK,aAAe,SAAY,CAC9B,MAAM,KAAK,sBAAsB,EACjC,MAAM,KAAK,aAAa,CAC1B,GAAG,EAEI,KAAK,WACd,CAEA,MAAa,SAASC,EAAgBC,EAAiD,CACrF,MAAM,KAAK,aAAa,EACxB,KAAK,OAAO,OAASD,EACrB,MAAM,KAAK,MAAM,SAAU,CACzB,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,UAAW,KAAK,OAAO,OACvB,WAAAC,CACF,CAAC,CACH,CAAC,EACD,MAAM,KAAK,sBAAsB,CACnC,CAEA,MAAa,MAAMC,EAAwBD,EAAiD,CAC1F,MAAM,KAAK,aAAa,EACxB,KAAK,OAAO,eAAiBC,EAC7B,MAAM,KAAK,MAAM,cAAe,CAC9B,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,mBAAoB,KAAK,OAAO,eAChC,WAAAD,CACF,CAAC,CACH,CAAC,EACD,MAAM,KAAK,sBAAsB,CACnC,CAEA,MAAa,MAAME,EAAeF,EAAiD,CACjF,MAAM,KAAK,aAAa,EACxB,MAAM,KAAK,MAAM,SAAU,CACzB,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OAAO,OAC3B,mBAAoB,KAAK,OAAO,eAChC,MAAAE,EACA,WAAAF,CACF,CAAC,CACH,CAAC,CACH,CAEA,MAAa,QAAQG,EAAgB,CACnC,aAAM,KAAK,aAAa,EAEjB,KAAK,MAAM,KAAMC,GAASA,EAAK,IAAMD,CAAM,CACpD,CAEA,MAAa,UAAW,CACtB,aAAM,KAAK,aAAa,EACjB,KAAK,KACd,CAEA,MAAa,OAAQ,CACnBE,EAAqB,EACrB,KAAK,OAAO,OAASC,EAAgB,EACrC,KAAK,OAAO,eAAiB,MAC/B,CAEO,kBAAkBC,EAAoD,CAC3E,KAAK,0BAA0B,KAAKA,CAAO,CAC7C,CAEO,+BAA+BA,EAAoD,CACxF,KAAK,0BAA4B,KAAK,0BAA0B,OAAQC,GAAMA,IAAMD,CAAO,CAC7F,CAEA,MAAc,cAAe,CAC3B,OAAI,KAAK,cAAgB,KAChB,KAAK,YAEL,KAAK,KAAK,KAAK,MAAM,CAEhC,CAEA,MAAc,uBAAuC,CACnD,IAAME,EAAiBC,EAAkB,KAAK,MAAM,EAEpD,GAAI,CAACC,EAAmBF,CAAc,EAAG,CACvC,IAAMG,EAAO,KAETC,EAAY,CACd,IAAK,SAAUC,EAAaC,EAAUC,EAAY,CAChD,OACEF,EAAOC,CAAG,GACVD,EAAOC,CAAG,EAAE,YACX,KAAK,UAAUD,EAAOC,CAAG,EAAE,SAAS,IAAM,KAAK,UAAUC,EAAM,SAAS,GACvE,KAAK,UAAUF,EAAOC,CAAG,EAAE,UAAU,IAAM,KAAK,UAAUC,EAAM,UAAU,GAC1E,KAAK,UAAUF,EAAOC,CAAG,EAAE,aAAa,IAAM,KAAK,UAAUC,EAAM,aAAa,IAElFJ,EAAK,qBAAqBE,EAAOC,CAAG,CAAC,EAGvCD,EAAOC,CAAG,EAAIC,EACP,EACT,CACF,EAEAL,EAAmBF,CAAc,EAAI,CACnC,sBAAuB,SAAY,CAAC,EACpC,eAAgB,IAAI,MAAM,CAAC,EAAGI,CAAS,CACzC,EACAF,EAAmBF,CAAc,EAAE,sBAAwB,SAAY,CACrE,IAAMQ,EAAoB,MAAM,KAAK,MACnC,iCAAiC,KAAK,OAAO,SAC3C,KAAK,OAAO,eAAiB,uBAAuB,KAAK,OAAO,iBAAmB,IAEvF,EACIA,GAAqBA,EAAkB,MACpBA,EAAkB,KACxB,QAASC,GAAkB,CACxCP,EAAmBF,CAAc,EAAE,eAAeS,EAAc,MAAM,EAAIA,CAC5E,CAAC,CAEL,EAGF,MAAMP,EAAmBF,CAAc,EAAE,sBAAsB,CACjE,CAEA,MAAc,cAAe,CAC3B,KAAK,MAAQ,CAAC,EACd,IAAMU,EAAc,MAAM,KAAK,MAAM,QAAQ,EACzCA,GAAeA,EAAY,MACbA,EAAY,KAClB,QAASC,GAAa,CAC9B,KAAK,MAAM,KAAK,IAAIC,EAAK,KAAK,OAAQD,CAAQ,CAAC,CACjD,CAAC,CAEL,CAEA,MAAc,qBAAqBE,EAAsC,CACnEA,GACF,KAAK,MAAM,QAASlB,GAAS,CAC3BA,EAAK,MACH,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,EAAE,EAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,EAAE,EACtFA,EAAK,IAAMkB,EAAsB,QACnC,KAAK,0BAA0B,QAASf,GAAY,CAClD,IAAMgB,EAAY,KAAK,cAAc,IAAIhB,CAAO,EAC1CiB,EAAWD,EAAYA,EAAU,IAAInB,EAAK,EAAE,EAAI,OACtDG,EAAQH,EAAMoB,CAAQ,EACjBD,GACH,KAAK,cAAc,IAAIhB,EAAS,IAAI,GAAK,EAE3C,KAAK,cAAc,IAAIA,CAAO,EAAE,IAAIH,EAAK,GAAIA,CAAI,CACnD,CAAC,CAEL,CAAC,CAEL,CACF","names":["src_exports","__export","Flow","Frigade","__toCommonJS","VERSION_NUMBER","import_cross_fetch","import_uuid","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","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","path","options","gracefulFetch","getHeaders","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","hasCompleted","targetingShouldHideFlow","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","copy","clone","frigadeGlobalState","getGlobalStateKey","updatedUserFlowState","isLastStep","nextStepId","NOT_STARTED_FLOW","currentStepId","key","Frigade","Fetchable","apiKey","config","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","generateGuestId","handler","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","previousUserFlowState","lastFlows","lastFlow"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/Fetchable.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export { Frigade } from './core/frigade'\n\nimport Flow from './core/flow'\nexport { Flow }\n\nexport { FlowStep } from './core/flow-step'\n\nexport * from './types'\n","export const VERSION_NUMBER = '0.2.0'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\nimport Flow from '../core/flow'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\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 (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\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 (window && window.localStorage && 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 < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(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","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.organizationId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: '//api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n this.config = {\n ...this.config,\n ...config,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade not initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport default class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public configYmlAsJson: any\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public rawData: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n /**\n * Whether the flow has been skipped or not\n */\n public isSkipped: boolean\n /**\n * Whether the flow is visible to the user based on the current user/group's state\n */\n public isVisible: boolean = false\n\n private readonly flowDataRaw: FlowDataRaw\n\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.rawData = flowDataRaw\n this.configYmlAsJson = flowDataYml\n this.title = this.configYmlAsJson.title\n this.subtitle = this.configYmlAsJson.subtitle\n\n const userFlowState = this.getUserFlowState()\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.isSkipped = userFlowState.flowState == SKIPPED_FLOW\n const hasCompleted = this.isCompleted || this.isSkipped\n const targetingShouldHideFlow =\n flowDataRaw.targetingLogic && userFlowState.shouldTrigger === false\n this.isVisible = !hasCompleted && !targetingShouldHideFlow\n const newSteps = new Map<string, FlowStep>()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[currentStep.id].actionType = STARTED_STEP\n copy.lastStepId = currentStep.id\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n currentStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[currentStep.id].actionType = COMPLETED_STEP\n copy.flowState = isLastStep ? COMPLETED_FLOW : STARTED_FLOW\n\n const nextStepId = Array.from(this.steps.keys())[index + 1]\n if (nextStepId) {\n copy.lastStepId = nextStepId\n }\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n // if all steps are now completed, mark flow completed\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n if (isLastStep) {\n await this.complete()\n } else {\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const currentStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n currentStep.isCompleted !== previousStep?.isCompleted ||\n currentStep.isStarted !== previousStep?.isStarted ||\n currentStep.isHidden !== previousStep?.isHidden ||\n currentStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(currentStep, previousStep ?? clone(currentStep))\n this.lastStepUpdate.set(handler, clone(currentStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj)\n })\n this.steps = newSteps\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = STARTED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n private optimisticallyMarkFlowCompleted() {\n this.isStarted = true\n this.isCompleted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = COMPLETED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n this.isVisible = false\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n this.getGlobalState().userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (\n (flow.id === this.id &&\n (flow.isCompleted !== previousFlow.isCompleted ||\n flow.isStarted !== previousFlow.isStarted ||\n flow.isSkipped !== previousFlow.isSkipped ||\n flow.isVisible !== previousFlow.isVisible)) ||\n JSON.stringify(flow.steps) !== JSON.stringify(previousFlow.steps)\n ) {\n handler(flow, previousFlow)\n }\n }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { cloneFlow, generateGuestId, resetAllLocalStorage } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.userId = userId\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.organizationId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.config.userId = generateGuestId()\n this.config.organizationId = undefined\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n target[key] &&\n target[key].flowState &&\n (JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState) ||\n JSON.stringify(target[key].stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger))\n ) {\n that.triggerEventHandlers(target[key])\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.organizationId ? `&foreignUserGroupId=${this.config.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n this.getGlobalState().previousFlows.set(\n flowData.slug,\n cloneFlow(this.flows[this.flows.length - 1])\n )\n })\n }\n }\n\n private async triggerEventHandlers(previousUserFlowState: UserFlowState) {\n if (previousUserFlowState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousUserFlowState.flowId) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n }\n}\n"],"mappings":"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","names":["src_exports","__export","Flow","Frigade","__toCommonJS","VERSION_NUMBER","import_cross_fetch","import_uuid","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","path","options","gracefulFetch","getHeaders","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","hasCompleted","targetingShouldHideFlow","newSteps","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","handler","wrapperHandler","flow","previousStep","h","NOT_STARTED_FLOW","currentStepId","key","previousFlow","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","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","Frigade","Fetchable","apiKey","config","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","generateGuestId","handler","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","cloneFlow","previousUserFlowState","lastFlow"]}
package/dist/index.d.ts CHANGED
@@ -183,12 +183,30 @@ interface FlowStep {
183
183
  * Function that marks the step completed
184
184
  */
185
185
  complete: (properties?: Record<string | number, any>) => Promise<void>;
186
+ /**
187
+ * Event handler for this given step's state changes
188
+ */
189
+ onStateChange: (callback: (step: FlowStep, previousStep?: FlowStep) => void) => void;
190
+ /**
191
+ * Removes the given callback from the list of event handlers
192
+ */
193
+ removeStateChangeHandler: (callback: (step: FlowStep, previousStep?: FlowStep) => void) => void;
194
+ }
195
+
196
+ interface FrigadeGlobalState {
197
+ refreshUserFlowStates: () => Promise<void>;
198
+ userFlowStates: Record<string, UserFlowState>;
199
+ onFlowStateChangeHandlerWrappers: Map<(flow: Flow, previousFlow: Flow) => void, (flow: Flow, previousFlow: Flow) => void>;
200
+ onStepStateChangeHandlerWrappers: Map<(step: FlowStep, previousStep: FlowStep) => void, (flow: Flow, previousFlow: Flow) => void>;
201
+ onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[];
202
+ previousFlows: Map<string, Flow>;
186
203
  }
187
204
 
188
205
  declare class Fetchable {
189
206
  config: FrigadeConfig;
190
207
  constructor(config: FrigadeConfig);
191
208
  fetch(path: string, options?: Record<any, any>): Promise<any>;
209
+ protected getGlobalState(): FrigadeGlobalState;
192
210
  }
193
211
 
194
212
  declare class Flow extends Fetchable {
@@ -199,7 +217,7 @@ declare class Flow extends Fetchable {
199
217
  /**
200
218
  * The raw data defined in `config.yml` as a JSON decoded object
201
219
  */
202
- rawData: Record<any, any>;
220
+ configYmlAsJson: any;
203
221
  /**
204
222
  * Ordered map from Step ID to step data. The `steps` array in `config.yml`
205
223
  */
@@ -215,7 +233,7 @@ declare class Flow extends Fetchable {
215
233
  /**
216
234
  * The metadata of the flow.
217
235
  */
218
- metadata: FlowDataRaw;
236
+ rawData: FlowDataRaw;
219
237
  /**
220
238
  * Whether the flow is completed or not
221
239
  */
@@ -232,11 +250,8 @@ declare class Flow extends Fetchable {
232
250
  * Whether the flow is visible to the user based on the current user/group's state
233
251
  */
234
252
  isVisible: boolean;
235
- /**
236
- * Nonce
237
- */
238
- nonce: string;
239
- private flowDataRaw;
253
+ private readonly flowDataRaw;
254
+ private lastStepUpdate;
240
255
  constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw);
241
256
  private initFromRawData;
242
257
  /**
@@ -269,6 +284,8 @@ declare class Flow extends Fetchable {
269
284
  * Get the number of completed steps for the current user in the current flow
270
285
  */
271
286
  getNumberOfCompletedSteps(): number;
287
+ onStateChange(handler: (flow: Flow, previousFlow: Flow) => void): void;
288
+ removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void): void;
272
289
  private getUserFlowState;
273
290
  private refreshUserFlowState;
274
291
  }
@@ -276,8 +293,6 @@ declare class Flow extends Fetchable {
276
293
  declare class Frigade extends Fetchable {
277
294
  private flows;
278
295
  private initPromise;
279
- private onFlowStateChangeHandlers;
280
- private previousFlows;
281
296
  constructor(apiKey: string, config?: FrigadeConfig);
282
297
  private init;
283
298
  identify(userId: string, properties?: Record<string, any>): Promise<void>;
@@ -286,12 +301,12 @@ declare class Frigade extends Fetchable {
286
301
  getFlow(flowId: string): Promise<Flow>;
287
302
  getFlows(): Promise<Flow[]>;
288
303
  reset(): Promise<void>;
289
- onFlowStateChange(handler: (flow: Flow, previousFlow?: Flow) => void): void;
290
- removeOnFlowStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void): void;
304
+ onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void): void;
305
+ removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void): void;
291
306
  private initIfNeeded;
292
307
  private refreshUserFlowStates;
293
308
  private refreshFlows;
294
309
  private triggerEventHandlers;
295
310
  }
296
311
 
297
- export { Flow, Frigade, FrigadeConfig, InternalConfig, UserFlowState, UserFlowStepState };
312
+ export { Flow, FlowStep, Frigade, FrigadeConfig, InternalConfig, UserFlowState, UserFlowStepState };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- var A="0.1.3";import W from"cross-fetch";import{v4 as K}from"uuid";var u="COMPLETED_FLOW",P="SKIPPED_FLOW",F="STARTED_FLOW",x="NOT_STARTED_FLOW",g="COMPLETED_STEP",S="STARTED_STEP",$="frigade-last-call-at-",H="frigade-last-call-data-",N="frigade-guest-key",k="guest_";function m(i){return JSON.parse(JSON.stringify(i))}function M(i){return{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json","X-Frigade-SDK-Version":A,"X-Frigade-SDK-Platform":"Javascript"}}}function R(i){return window&&window.localStorage?window.localStorage.getItem(i):null}function L(i,l){window&&window.localStorage&&window.localStorage.setItem(i,l)}function J(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(i=>{i.startsWith("frigade-")&&window.localStorage.removeItem(i)})}async function G(i,l){let t=$+i,e=H+i;if(window&&window.localStorage&&l&&l.body&&l.method==="POST"){let s=R(t),n=R(e);if(s&&n&&n==l.body){let c=new Date(s);if(new Date().getTime()-c.getTime()<1e3)return I()}L(t,new Date().toISOString()),L(e,l.body)}let r;try{r=await W(i,l)}catch(s){return I(s)}return r?r.staus>=400?I(r.statusText):r.json():I()}function I(i){return i&&console.log("Call to Frigade failed",i),{json:()=>({})}}function O(){if(typeof window<"u"&&typeof window.localStorage<"u"){let i=R(N);return i||(i=`${k}${K()}`,window.localStorage.setItem(N,i)),i}}var a={};function d(i){return`${i.__instanceId}-${i.apiKey}:${i.userId??""}:${i.organizationId??""}`}var h=class{constructor(l){this.config={apiKey:"",apiUrl:"//api.frigade.com/v1/public",userId:O(),__instanceId:Math.random().toString(36).substring(7)};this.config={...this.config,...l}}async fetch(l,t){return G(`${this.config.apiUrl}${l}`,{...t??{},...M(this.config.apiKey)})}};var w=class extends h{constructor(t,e){super(t);this.isVisible=!1;this.nonce=Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15);this.flowDataRaw=e,this.initFromRawData(e)}initFromRawData(t){let e=JSON.parse(t.data),r=e.steps??e.data??[];this.id=t.slug,this.metadata=t,this.rawData=e,this.title=this.rawData.title,this.subtitle=this.rawData.subtitle;let s=this.getUserFlowState();this.isCompleted=s.flowState==u,this.isStarted=s.flowState==F,this.isSkipped=s.flowState==P;let n=this.isCompleted||this.isSkipped,c=t.targetingLogic&&s.shouldTrigger===!1;this.isVisible=!n&&!c,this.steps=new Map,r.forEach((f,D)=>{let y=s.stepStates[f.id],E={...f,isCompleted:y.actionType==g,isStarted:y.actionType==S,isHidden:y.hidden,isBlocked:y.blocked,order:D};E.start=async C=>{let o=this.steps.get(f.id);if(o.isStarted||o.isCompleted)return;o.isStarted=!0;let T=m(a[d(this.config)].userFlowStates[this.id]);T.stepStates[o.id].actionType=S,T.lastStepId=o.id,a[d(this.config)].userFlowStates[this.id]=T,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:o.id,data:C??{},createdAt:new Date().toISOString(),actionType:S})}),await this.refreshUserFlowState();let p=this.getUserFlowState();o.isCompleted=p.stepStates[o.id].actionType==g,o.isStarted=p.stepStates[o.id].actionType==S},E.complete=async C=>{let o=this.steps.get(f.id);if(o.isCompleted)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size;o.isCompleted=!0,this.isStarted=!0;let b=m(a[d(this.config)].userFlowStates[this.id]);b.stepStates[o.id].actionType=g,b.flowState=p?u:F;let U=Array.from(this.steps.keys())[D+1];U&&(b.lastStepId=U),p&&this.optimisticallyMarkFlowCompleted(),a[d(this.config)].userFlowStates[this.id]=b,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:o.id,data:C??{},createdAt:new Date().toISOString(),actionType:g})}),p?await this.complete():await this.refreshUserFlowState();let v=this.getUserFlowState();o.isCompleted=v.stepStates[o.id].actionType==g,o.isStarted=v.stepStates[o.id].actionType==S},this.steps.set(f.id,E)})}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e=m(a[d(this.config)].userFlowStates[this.id]);e.flowState=F,a[d(this.config)].userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:F})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:u})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=m(a[d(this.config)].userFlowStates[this.id]);t.flowState=u,a[d(this.config)].userFlowStates[this.id]=t,this.isVisible=!1}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:P})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,a[d(this.config)].userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:x})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let e=Array.from(this.steps.keys()).find(r=>this.steps.get(r).isCompleted===!1)??Array.from(this.steps.keys())[0];return this.steps.get(e)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getUserFlowState(){return a[d(this.config)].userFlowStates[this.id]}async refreshUserFlowState(){await a[d(this.config)].refreshUserFlowStates()}};var _=class extends h{constructor(t,e){super({apiKey:t,...e});this.flows=[];this.onFlowStateChangeHandlers=[];this.previousFlows=new Map;this.init(this.config)}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,e){await this.initIfNeeded(),this.config.userId=t,await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),await this.refreshUserFlowStates()}async group(t,e){await this.initIfNeeded(),this.config.organizationId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,properties:e})}),await this.refreshUserFlowStates()}async track(t,e){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,event:t,properties:e})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){J(),this.config.userId=O(),this.config.organizationId=void 0}onFlowStateChange(t){this.onFlowStateChangeHandlers.push(t)}removeOnFlowStateChangeHandler(t){this.onFlowStateChangeHandlers=this.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(!a[t]){let e=this,r={set:function(s,n,c){return s[n]&&s[n].flowState&&(JSON.stringify(s[n].flowState)!==JSON.stringify(c.flowState)||JSON.stringify(s[n].stepStates)!==JSON.stringify(c.stepStates)||JSON.stringify(s[n].shouldTrigger)!==JSON.stringify(c.shouldTrigger))&&e.triggerEventHandlers(s[n]),s[n]=c,!0}};a[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},r)},a[t].refreshUserFlowStates=async()=>{let s=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.organizationId?`&foreignUserGroupId=${this.config.organizationId}`:""}`);s&&s.data&&s.data.forEach(c=>{a[t].userFlowStates[c.flowId]=c})}}await a[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(r=>{this.flows.push(new w(this.config,r))})}async triggerEventHandlers(t){t&&this.flows.forEach(e=>{e.nonce=Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15),e.id==t.flowId&&this.onFlowStateChangeHandlers.forEach(r=>{let s=this.previousFlows.get(r),n=s?s.get(e.id):void 0;r(e,n),s||this.previousFlows.set(r,new Map),this.previousFlows.get(r).set(e.id,e)})})}};export{w as Flow,_ as Frigade};
2
+ var N="0.2.0";import k from"cross-fetch";import{v4 as K}from"uuid";var c={};function I(i){return`${i.__instanceId}-${i.apiKey}:${i.userId??""}:${i.organizationId??""}`}var u=class{constructor(r){this.config={apiKey:"",apiUrl:"//api.frigade.com/v1/public",userId:O(),__instanceId:Math.random().toString(36).substring(7)};this.config={...this.config,...r}}async fetch(r,t){return H(`${this.config.apiUrl}${r}`,{...t??{},...L(this.config.apiKey)})}getGlobalState(){let r=I(this.config);if(!c[r])throw new Error("Frigade not initialized");return c[r]}};var w=class extends u{constructor(t,e){super(t);this.isVisible=!1;this.lastStepUpdate=new Map;this.flowDataRaw=e,this.initFromRawData(e)}initFromRawData(t){let e=JSON.parse(t.data),o=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();this.isCompleted=s.flowState==b,this.isStarted=s.flowState==T,this.isSkipped=s.flowState==P;let d=this.isCompleted||this.isSkipped,p=t.targetingLogic&&s.shouldTrigger===!1;this.isVisible=!d&&!p;let D=new Map;o.forEach((h,G)=>{let C=s.stepStates[h.id],y={...h,isCompleted:C.actionType==F,isStarted:C.actionType==m,isHidden:C.hidden,isBlocked:C.blocked,order:G};y.start=async S=>{let a=this.steps.get(h.id);if(a.isStarted||a.isCompleted)return;a.isStarted=!0;let g=f(this.getGlobalState().userFlowStates[this.id]);g.stepStates[a.id].actionType=m,g.lastStepId=a.id,this.getGlobalState().userFlowStates[this.id]=g,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:a.id,data:S??{},createdAt:new Date().toISOString(),actionType:m})}),await this.refreshUserFlowState();let l=this.getUserFlowState();a.isCompleted=l.stepStates[a.id].actionType==F,a.isStarted=l.stepStates[a.id].actionType==m},y.complete=async S=>{let a=this.steps.get(h.id);if(a.isCompleted)return;let l=this.getNumberOfCompletedSteps()+1==this.steps.size;a.isCompleted=!0,this.isStarted=!0;let n=f(this.getGlobalState().userFlowStates[this.id]);n.stepStates[a.id].actionType=F,n.flowState=l?b:T;let v=Array.from(this.steps.keys())[G+1];v&&(n.lastStepId=v),l&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=n,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:a.id,data:S??{},createdAt:new Date().toISOString(),actionType:F})}),l?await this.complete():await this.refreshUserFlowState();let A=this.getUserFlowState();a.isCompleted=A.stepStates[a.id].actionType==F,a.isStarted=A.stepStates[a.id].actionType==m},y.onStateChange=S=>{let a=g=>{if(g.id!==this.id)return;let l=g.steps.get(h.id),n=this.lastStepUpdate.get(S);(l.isCompleted!==(n==null?void 0:n.isCompleted)||l.isStarted!==(n==null?void 0:n.isStarted)||l.isHidden!==(n==null?void 0:n.isHidden)||l.isBlocked!==(n==null?void 0:n.isBlocked))&&(S(l,n??f(l)),this.lastStepUpdate.set(S,f(l)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(S,a),this.getGlobalState().onFlowStateChangeHandlers.push(a)},y.removeStateChangeHandler=S=>{let a=this.getGlobalState().onStepStateChangeHandlerWrappers.get(S);a&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(g=>g!==a))},D.set(h.id,y)}),this.steps=D}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e=f(this.getGlobalState().userFlowStates[this.id]);e.flowState=T,this.getGlobalState().userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:T})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:b})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=f(this.getGlobalState().userFlowStates[this.id]);t.flowState=b,this.getGlobalState().userFlowStates[this.id]=t,this.isVisible=!1}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:P})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,this.getGlobalState().userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:x})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let e=Array.from(this.steps.keys()).find(o=>this.steps.get(o).isCompleted===!1)??Array.from(this.steps.keys())[0];return this.steps.get(e)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}onStateChange(t){let e=(o,s)=>{(o.id===this.id&&(o.isCompleted!==s.isCompleted||o.isStarted!==s.isStarted||o.isSkipped!==s.isSkipped||o.isVisible!==s.isVisible)||JSON.stringify(o.steps)!==JSON.stringify(s.steps))&&t(o,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(o=>o!==e))}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}async refreshUserFlowState(){await this.getGlobalState().refreshUserFlowStates()}};var b="COMPLETED_FLOW",P="SKIPPED_FLOW",T="STARTED_FLOW",x="NOT_STARTED_FLOW",F="COMPLETED_STEP",m="STARTED_STEP",$="frigade-last-call-at-",z="frigade-last-call-data-",J="frigade-guest-key",V="guest_";function U(i){let r=new w(i.config,i.rawData);return r.isCompleted=i.isCompleted,r.isStarted=i.isStarted,r.isSkipped=i.isSkipped,r.isVisible=i.isVisible,r.steps=i.steps,r}function f(i){return JSON.parse(JSON.stringify(i))}function L(i){return{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json","X-Frigade-SDK-Version":N,"X-Frigade-SDK-Platform":"Javascript"}}}function R(i){return window&&window.localStorage?window.localStorage.getItem(i):null}function W(i,r){window&&window.localStorage&&window.localStorage.setItem(i,r)}function M(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(i=>{i.startsWith("frigade-")&&window.localStorage.removeItem(i)})}async function H(i,r){let t=$+i,e=z+i;if(window&&window.localStorage&&r&&r.body&&r.method==="POST"){let s=R(t),d=R(e);if(s&&d&&d==r.body){let p=new Date(s);if(new Date().getTime()-p.getTime()<1e3)return E()}W(t,new Date().toISOString()),W(e,r.body)}let o;try{o=await k(i,r)}catch(s){return E(s)}return o?o.staus>=400?E(o.statusText):o.json():E()}function E(i){return i&&console.log("Call to Frigade failed",i),{json:()=>({})}}function O(){if(typeof window<"u"&&typeof window.localStorage<"u"){let i=R(J);return i||(i=`${V}${K()}`,window.localStorage.setItem(J,i)),i}}var _=class extends u{constructor(t,e){super({apiKey:t,...e});this.flows=[];this.init(this.config)}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,e){await this.initIfNeeded(),this.config.userId=t,await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),await this.refreshUserFlowStates()}async group(t,e){await this.initIfNeeded(),this.config.organizationId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,properties:e})}),await this.refreshUserFlowStates()}async track(t,e){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,event:t,properties:e})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){M(),this.config.userId=O(),this.config.organizationId=void 0}onStateChange(t){this.getGlobalState().onFlowStateChangeHandlers.push(t)}removeStateChangeHandler(t){this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(e=>e!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=I(this.config);if(!c[t]){let e=this,o={set:function(s,d,p){return s[d]&&s[d].flowState&&(JSON.stringify(s[d].flowState)!==JSON.stringify(p.flowState)||JSON.stringify(s[d].stepStates)!==JSON.stringify(p.stepStates)||JSON.stringify(s[d].shouldTrigger)!==JSON.stringify(p.shouldTrigger))&&e.triggerEventHandlers(s[d]),s[d]=p,!0}};c[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},o),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map},c[t].refreshUserFlowStates=async()=>{let s=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.organizationId?`&foreignUserGroupId=${this.config.organizationId}`:""}`);s&&s.data&&s.data.forEach(p=>{c[t].userFlowStates[p.flowId]=p})}}await c[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(o=>{this.flows.push(new w(this.config,o)),this.getGlobalState().previousFlows.set(o.slug,U(this.flows[this.flows.length-1]))})}async triggerEventHandlers(t){t&&this.flows.forEach(e=>{e.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(o=>{let s=this.getGlobalState().previousFlows.get(e.id);o(e,s),this.getGlobalState().previousFlows.set(e.id,U(e))})})}};export{w as Flow,_ 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.1.3'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\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 (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\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 (window && window.localStorage && 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 < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(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","import { FrigadeConfig, UserFlowState } from '../types'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\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.organizationId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: '//api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n this.config = {\n ...this.config,\n ...config,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport default class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public rawData: Record<any, any>\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public metadata: 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 /**\n * Nonce\n */\n public nonce =\n Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)\n\n private flowDataRaw: FlowDataRaw\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.metadata = flowDataRaw\n this.rawData = flowDataYml\n this.title = this.rawData.title\n this.subtitle = this.rawData.subtitle\n\n const userFlowState = this.getUserFlowState()\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 this.steps = new Map()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const copy = clone(\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id]\n )\n copy.stepStates[currentStep.id].actionType = STARTED_STEP\n copy.lastStepId = currentStep.id\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n currentStep.isCompleted = true\n this.isStarted = true\n const copy = clone(\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id]\n )\n\n copy.stepStates[currentStep.id].actionType = COMPLETED_STEP\n copy.flowState = isLastStep ? COMPLETED_FLOW : STARTED_FLOW\n\n const nextStepId = Array.from(this.steps.keys())[index + 1]\n if (nextStepId) {\n copy.lastStepId = nextStepId\n }\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = copy\n\n // if all steps are now completed, mark flow completed\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n if (isLastStep) {\n await this.complete()\n } else {\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n this.steps.set(step.id, stepObj)\n })\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const copy = clone(frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id])\n copy.flowState = STARTED_FLOW\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n private optimisticallyMarkFlowCompleted() {\n this.isStarted = true\n this.isCompleted = true\n const copy = clone(frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id])\n copy.flowState = COMPLETED_FLOW\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = copy\n this.isVisible = false\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await frigadeGlobalState[getGlobalStateKey(this.config)].refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { generateGuestId, resetAllLocalStorage } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n private onFlowStateChangeHandlers: ((flow: Flow, previousFlow?: Flow) => void)[] = []\n private previousFlows: Map<(flow: Flow, previousFlow: Flow) => void, Map<string, Flow>> =\n new Map()\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.userId = userId\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.organizationId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.config.userId = generateGuestId()\n this.config.organizationId = undefined\n }\n\n public onFlowStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.onFlowStateChangeHandlers.push(handler)\n }\n\n public removeOnFlowStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.onFlowStateChangeHandlers = this.onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n target[key] &&\n target[key].flowState &&\n (JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState) ||\n JSON.stringify(target[key].stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger))\n ) {\n that.triggerEventHandlers(target[key])\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.organizationId ? `&foreignUserGroupId=${this.config.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n })\n }\n }\n\n private async triggerEventHandlers(previousUserFlowState: UserFlowState) {\n if (previousUserFlowState) {\n this.flows.forEach((flow) => {\n flow.nonce =\n Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)\n if (flow.id == previousUserFlowState.flowId) {\n this.onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlows = this.previousFlows.get(handler)\n const lastFlow = lastFlows ? lastFlows.get(flow.id) : undefined\n handler(flow, lastFlow)\n if (!lastFlows) {\n this.previousFlows.set(handler, new Map())\n }\n this.previousFlows.get(handler).set(flow.id, flow)\n })\n }\n })\n }\n }\n}\n"],"mappings":"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","names":["VERSION_NUMBER","fetch","uuidv4","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","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","path","options","gracefulFetch","getHeaders","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","hasCompleted","targetingShouldHideFlow","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","copy","clone","frigadeGlobalState","getGlobalStateKey","updatedUserFlowState","isLastStep","nextStepId","NOT_STARTED_FLOW","currentStepId","key","Frigade","Fetchable","apiKey","config","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","generateGuestId","handler","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","previousUserFlowState","lastFlows","lastFlow"]}
1
+ {"version":3,"sources":["../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/Fetchable.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export const VERSION_NUMBER = '0.2.0'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\nimport Flow from '../core/flow'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\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 (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\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 (window && window.localStorage && 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 < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(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","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.organizationId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: '//api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n this.config = {\n ...this.config,\n ...config,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade not initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport default class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public configYmlAsJson: any\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public rawData: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n /**\n * Whether the flow has been skipped or not\n */\n public isSkipped: boolean\n /**\n * Whether the flow is visible to the user based on the current user/group's state\n */\n public isVisible: boolean = false\n\n private readonly flowDataRaw: FlowDataRaw\n\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.rawData = flowDataRaw\n this.configYmlAsJson = flowDataYml\n this.title = this.configYmlAsJson.title\n this.subtitle = this.configYmlAsJson.subtitle\n\n const userFlowState = this.getUserFlowState()\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.isSkipped = userFlowState.flowState == SKIPPED_FLOW\n const hasCompleted = this.isCompleted || this.isSkipped\n const targetingShouldHideFlow =\n flowDataRaw.targetingLogic && userFlowState.shouldTrigger === false\n this.isVisible = !hasCompleted && !targetingShouldHideFlow\n const newSteps = new Map<string, FlowStep>()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.stepStates[currentStep.id].actionType = STARTED_STEP\n copy.lastStepId = currentStep.id\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n\n currentStep.isCompleted = true\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n\n copy.stepStates[currentStep.id].actionType = COMPLETED_STEP\n copy.flowState = isLastStep ? COMPLETED_FLOW : STARTED_FLOW\n\n const nextStepId = Array.from(this.steps.keys())[index + 1]\n if (nextStepId) {\n copy.lastStepId = nextStepId\n }\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n this.getGlobalState().userFlowStates[this.id] = copy\n\n // if all steps are now completed, mark flow completed\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n if (isLastStep) {\n await this.complete()\n } else {\n await this.refreshUserFlowState()\n }\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const currentStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n currentStep.isCompleted !== previousStep?.isCompleted ||\n currentStep.isStarted !== previousStep?.isStarted ||\n currentStep.isHidden !== previousStep?.isHidden ||\n currentStep.isBlocked !== previousStep?.isBlocked\n ) {\n handler(currentStep, previousStep ?? clone(currentStep))\n this.lastStepUpdate.set(handler, clone(currentStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj)\n })\n this.steps = newSteps\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = STARTED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n private optimisticallyMarkFlowCompleted() {\n this.isStarted = true\n this.isCompleted = true\n const copy = clone(this.getGlobalState().userFlowStates[this.id])\n copy.flowState = COMPLETED_FLOW\n this.getGlobalState().userFlowStates[this.id] = copy\n this.isVisible = false\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n this.getGlobalState().userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (\n (flow.id === this.id &&\n (flow.isCompleted !== previousFlow.isCompleted ||\n flow.isStarted !== previousFlow.isStarted ||\n flow.isSkipped !== previousFlow.isSkipped ||\n flow.isVisible !== previousFlow.isVisible)) ||\n JSON.stringify(flow.steps) !== JSON.stringify(previousFlow.steps)\n ) {\n handler(flow, previousFlow)\n }\n }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = this.getGlobalState().userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await this.getGlobalState().refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { cloneFlow, generateGuestId, resetAllLocalStorage } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.userId = userId\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.organizationId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.config.userId = generateGuestId()\n this.config.organizationId = undefined\n }\n\n public onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n target[key] &&\n target[key].flowState &&\n (JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState) ||\n JSON.stringify(target[key].stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger))\n ) {\n that.triggerEventHandlers(target[key])\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.organizationId ? `&foreignUserGroupId=${this.config.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n this.getGlobalState().previousFlows.set(\n flowData.slug,\n cloneFlow(this.flows[this.flows.length - 1])\n )\n })\n }\n }\n\n private async triggerEventHandlers(previousUserFlowState: UserFlowState) {\n if (previousUserFlowState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousUserFlowState.flowId) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n }\n}\n"],"mappings":"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","names":["VERSION_NUMBER","fetch","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","path","options","gracefulFetch","getHeaders","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","hasCompleted","targetingShouldHideFlow","newSteps","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","copy","clone","updatedUserFlowState","isLastStep","nextStepId","handler","wrapperHandler","flow","previousStep","h","NOT_STARTED_FLOW","currentStepId","key","previousFlow","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","cloneFlow","flow","newFlow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","Frigade","Fetchable","apiKey","config","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","generateGuestId","handler","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","cloneFlow","previousUserFlowState","lastFlow"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frigade/js",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "The official Javascript SDK for Frigade.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",