@frigade/js 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -6
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var I=Object.defineProperty,Q=Object.defineProperties,Z=Object.getOwnPropertyDescriptor,tt=Object.getOwnPropertyDescriptors,et=Object.getOwnPropertyNames,P=Object.getOwnPropertySymbols;var A=Object.prototype.hasOwnProperty,it=Object.prototype.propertyIsEnumerable;var _=(a,s,t)=>s in a?I(a,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[s]=t,f=(a,s)=>{for(var t in s||(s={}))A.call(s,t)&&_(a,t,s[t]);if(P)for(var t of P(s))it.call(s,t)&&_(a,t,s[t]);return a},y=(a,s)=>Q(a,tt(s));var st=(a,s)=>{for(var t in s)I(a,t,{get:s[t],enumerable:!0})},at=(a,s,t,e)=>{if(s&&typeof s=="object"||typeof s=="function")for(let i of et(s))!A.call(a,i)&&i!==t&&I(a,i,{get:()=>s[i],enumerable:!(e=Z(s,i))||e.enumerable});return a};var rt=a=>at(I({},"__esModule",{value:!0}),a);var h=(a,s,t)=>new Promise((e,i)=>{var o=r=>{try{l(t.next(r))}catch(d){i(d)}},n=r=>{try{l(t.throw(r))}catch(d){i(d)}},l=r=>r.done?e(r.value):Promise.resolve(r.value).then(o,n);l((t=t.apply(a,s)).next())});var ct={};st(ct,{Flow:()=>w,Frigade:()=>T});module.exports=rt(ct);var x="0.2.20";var q=require("uuid");var g={};function F(a){var s,t;return`${a.__instanceId}-${a.apiKey}:${(s=a.userId)!=null?s:""}:${(t=a.groupId)!=null?t:""}`}var m=class{constructor(s){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:D(),__instanceId:Math.random().toString(12).substring(4)};let t=Object.fromEntries(Object.entries(s).filter(([e,i])=>i!=null));this.config=f(f({},this.config),t)}fetch(s,t){return h(this,null,function*(){return this.config.__readOnly?S():k(this.getAPIUrl(s),f(f({keepalive:!0},t!=null?t:{}),N(this.config.apiKey)))})}getAPIUrl(s){let t="/v1/public";return new URL(`${t}${s}`,this.config.apiUrl.replace(t,"")).toString()}getGlobalState(){let s=F(this.config);if(!g[s])throw new Error("Frigade has not yet been initialized");return g[s]}};var w=class extends m{constructor({config:t,id:e}){super(t);this._isVisible=!1;this.lastStepUpdate=new Map;this.id=e,this.init()}get isVisible(){return this._isVisible===!1?!1:this.getGlobalState().rulesGraph.isFlowVisible(this.id)}set isVisible(t){this._isVisible=t}reload(){this.init()}resyncState(t){var i,o;let e=t!=null?t:this.getStatefulFlow();this.rawData=e,this.title=(i=e==null?void 0:e.data)==null?void 0:i.title,this.subtitle=(o=e==null?void 0:e.data)==null?void 0:o.subtitle,this.isCompleted=e.$state.completed,this.isStarted=e.$state.started,this.isSkipped=e.$state.skipped,this._isVisible=e.$state.visible,e.data.steps.forEach((n,l)=>{var p;let r=this.initStepFromStatefulStep(n,l),d=(p=this.steps)==null?void 0:p.get(n.id);d&&(d.$state=r.$state)})}initStepFromStatefulStep(t,e){return y(f({},t),{flow:this,$state:y(f({},t.$state),{lastActionAt:t.$state.lastActionAt?new Date(t.$state.lastActionAt):void 0}),order:e})}init(){let t=this.getStatefulFlow();this.resyncState();let e=new Map;t.data.steps.forEach((i,o)=>{let n=this.initStepFromStatefulStep(i,o);n.start=l=>h(this,null,function*(){let r=this.steps.get(i.id);if(this.getCurrentStep().id===r.id&&r.$state.started)return;let d=u(this.getGlobalState().flowStates[this.id]);d.data.steps[r.order].$state.started=!0,d.data.steps[r.order].$state.lastActionAt=new Date,d.$state.lastActionAt=new Date,d.$state.currentStepId=r.id,d.$state.currentStepIndex=r.order,this.getGlobalState().flowStates[this.id]=d,this.resyncState(),r.$state.completed||(yield this.sendFlowStateToAPI(K,l,r.id))}),n.complete=l=>h(this,null,function*(){let r=this.steps.get(i.id);if(r.$state.completed)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size,c=u(this.getGlobalState().flowStates[this.id]);c.$state.started=!0,c.data.steps[r.order].$state.completed=!0,c.data.steps[r.order].$state.started=!0,c.data.steps[r.order].$state.lastActionAt=new Date,p||(c.$state.currentStepId=this.getStepByIndex(r.order+1).id,c.$state.currentStepIndex=r.order+1),p&&(c.$state.completed=!0),this.getGlobalState().flowStates[this.id]=c,this.resyncState(),p&&this.optimisticallyMarkFlowCompleted(),yield this.sendFlowStateToAPI(J,l,r.id)}),n.reset=()=>h(this,null,function*(){let l=this.steps.get(i.id);if(!l.$state.completed)return;let r=u(this.getGlobalState().flowStates[this.id]);r.data.steps[l.order].$state.started=!1,r.data.steps[l.order].$state.completed=!1,r.data.steps[l.order].$state.lastActionAt=void 0,this.getGlobalState().flowStates[this.id]=r,this.resyncState(),yield this.sendFlowStateToAPI(H,void 0,l.id)}),n.onStateChange=l=>{let r=d=>{if(d.id!==this.id)return;let p=d.steps.get(i.id),c=this.lastStepUpdate.get(l);(p.$state.completed!==(c==null?void 0:c.$state.completed)||p.$state.started!==(c==null?void 0:c.$state.started)||p.$state.visible!==(c==null?void 0:c.$state.visible)||p.$state.blocked!==(c==null?void 0:c.$state.blocked))&&(l(p,c!=null?c:u(p)),this.lastStepUpdate.set(l,u(p)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(l,r),this.getGlobalState().onFlowStateChangeHandlers.push(r)},n.removeStateChangeHandler=l=>{let r=this.getGlobalState().onStepStateChangeHandlerWrappers.get(l);r&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(d=>d!==r))},e.set(i.id,n)}),this.steps=e,this.getGlobalState().variables&&this.getGlobalState().variables[this.id]&&Object.keys(this.getGlobalState().variables[this.id]).length>0&&this.applyVariables(this.getGlobalState().variables[this.id])}start(t){return h(this,null,function*(){if(this.isStarted||this.isCompleted)return;let e=u(this.getGlobalState().flowStates[this.id]);e.$state.started=!0,this.getGlobalState().flowStates[this.id]=e,this.resyncState(),yield this.sendFlowStateToAPI(W,t)})}complete(t){return h(this,null,function*(){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),yield this.sendFlowStateToAPI(M,t))})}skip(t){return h(this,null,function*(){this.isSkipped||(this.optimisticallyMarkFlowSkipped(),yield this.sendFlowStateToAPI(L,t))})}forward(t){return h(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e?yield e.start(t):yield this.complete(t)})}back(t){return h(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&(yield e.start(t))})}restart(){return h(this,null,function*(){this.optimisticallyMarkFlowNotStarted(),yield this.sendFlowStateToAPI(U)})}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){var t;return(t=this.steps.get(this.getStatefulFlow().$state.currentStepId))!=null?t:this.steps.get(Array.from(this.steps.keys())[0])}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.completed).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.visible).length}onStateChange(t){let e=(i,o)=>{i.id===this.id&&(i.isCompleted!==(o==null?void 0:o.isCompleted)||i.isStarted!==(o==null?void 0:o.isStarted)||i.isSkipped!==(o==null?void 0:o.isSkipped)||i.isVisible!==(o==null?void 0:o.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(o==null?void 0:o.steps))&&t(i,o)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,e),this.getGlobalState().onFlowStateChangeHandlers.push(e)}removeStateChangeHandler(t){let e=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);e&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(i=>i!==e))}applyVariables(t){var i,o;let e=n=>{let l=n.match(/\${(.*?)}/g);return l&&l.forEach(r=>{let d=r.replace("${","").replace("}","");t[d]&&(n=n.replace(r,t[d]))}),n};this.title=e((i=this.title)!=null?i:""),this.subtitle=e((o=this.subtitle)!=null?o:""),this.steps.forEach(n=>{Object.keys(n).forEach(l=>{typeof n[l]=="string"&&(n[l]=e(n[l]))})}),this.getGlobalState().variables={},this.getGlobalState().variables[this.id]=t}getStatefulFlow(){return this.getGlobalState().flowStates[this.id]}optimisticallyMarkFlowCompleted(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.completed=!0,t.$state.started=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}optimisticallyMarkFlowNotStarted(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.completed=!1,t.$state.started=!1,t.$state.visible=!0,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}sendFlowStateToAPI(t,e,i){return h(this,null,function*(){let o=new Date;this.getGlobalState().lastSyncDate=o;let n=yield this.fetch("/flowStates",{method:"POST",body:JSON.stringify({userId:this.config.userId,groupId:this.config.groupId,flowSlug:this.id,stepId:i!=null?i:this.getCurrentStep().id,data:e?JSON.stringify(e):{},actionType:t,createdAt:o})});o<this.getGlobalState().lastSyncDate||(yield this.getGlobalState().refreshStateFromAPI(n))})}optimisticallyMarkFlowSkipped(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.skipped=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}register(t){this.getGlobalState().rulesGraph.register(this.id,t)}unregister(){this.getGlobalState().rulesGraph.unregister(this.id)}};var H="NOT_STARTED_STEP",M="COMPLETED_FLOW",L="SKIPPED_FLOW",W="STARTED_FLOW",U="NOT_STARTED_FLOW",J="COMPLETED_STEP",K="STARTED_STEP",V="frigade-guest-key",R="guest_",ot="get-cache-",$="fr-js-";function G(a){return new w({config:a.config,id:a.id})}function u(a){return JSON.parse(JSON.stringify(a))}function N(a){return{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json","X-Frigade-SDK-Version":x,"X-Frigade-SDK-Platform":"Javascript"}}}function nt(a){return b()?window.localStorage.getItem(`${$}${a}`):null}function lt(a,s){b()&&window.localStorage.setItem(`${$}${a}`,s)}function B(){Object.keys(g).forEach(a=>{a.startsWith(ot)&&delete g[a]})}function X(){b()&&Object.keys(window.localStorage).forEach(a=>{a.startsWith($)&&window.localStorage.removeItem(a)})}var O=class{constructor(){this.queue=[];this.ttlInMS=500;this.cacheSize=5}push(s){let t=new Date;this.queue.length>=this.cacheSize&&this.queue.shift(),this.queue.push({call:s,time:t.getTime()})}hasIdenticalCall(s){let t=new Date;return this.queue=this.queue.filter(e=>t.getTime()-e.time<this.ttlInMS),this.queue.some(e=>e.call===s)}},j=new O;function k(a,s){return h(this,null,function*(){var e;if(typeof globalThis.fetch!="function")return S("- Attempted to call fetch() in an environment that doesn't support it.");if(b()&&s&&s.body&&s.method==="POST"){let i=`${a}${JSON.stringify((e=s.body)!=null?e:{})}`;if(j.hasIdenticalCall(i))return S();j.push(i)}let t;try{t=fetch(a,s),t=yield t}catch(i){return S(i)}if(!t)return S("Received an empty response");if(t.status>=400)return S(t.statusText);try{if(t.status===204)return S();let i;try{i=yield t.json()}catch(o){return S()}return i.error?S(i.error):i}catch(i){return S(i)}})}function S(a){return a&&console.log("Call to Frigade failed",a),{json:()=>({})}}function D(){if(b()){let a=nt(V);return a||(a=`${R}${(0,q.v4)()}`,lt(V,a)),a}}function b(){return typeof window!="undefined"&&typeof window.document!="undefined"&&typeof window.localStorage!="undefined"}var C=class{constructor(s,t){this.graph=new Map;this.registry=new Map;this.ruleOrder=[];var e,i;this._rawGraphData=s,t&&(this.registry=t),this.ruleOrder=(e=s==null?void 0:s.ruleOrder)!=null?e:[],this.ingestGraphData((i=s==null?void 0:s.graph)!=null?i:{})}get rawGraphData(){return this._rawGraphData}ingestGraphData(s){this.graph=new Map(Object.entries(s)),this.fireCallbacks()}fireCallbacks(){for(let[s,t]of this.registry)typeof t=="function"&&t(this.isFlowVisible(s))}isFlowVisible(s){let t=this.graph.get(s);return t?t.visible===!1?!1:t.edges.length===0?!0:this.findRegisteredDescendant(s)==null:!0}register(s,t){this.registry.set(s,t),this.fireCallbacks()}unregister(s){this.registry.delete(s),this.fireCallbacks()}getRegistry(){return this.registry}findRegisteredDescendant(s,t=s,e){let i=this.graph.get(s);if(i==null)return;if(this.registry.has(s)&&t!==s)return i;let o;if(i.edges.length>0)for(let n of i.edges){if(e!=null&&n.ruleId!==e)continue;let l=this.findRegisteredDescendant(n.head,t,e!=null?e:n.ruleId);if(l!=null&&l.visible){o=l;break}}return o}};var T=class extends m{constructor(t,e){super(f({apiKey:t},e));this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=()=>h(this,null,function*(){document.visibilityState==="visible"&&(yield this.refreshStateFromAPI())});this.init(this.config),b()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(b()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=F(this.config);g[t]&&(g[t].onFlowStateChangeHandlers=[])}}init(t){return h(this,null,function*(){return this.config=f(f({},this.config),t),this.initPromise=(()=>h(this,null,function*(){var e;this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(R))&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})),yield this.refreshStateFromAPI()}))(),this.initPromise})}identify(t,e){return h(this,null,function*(){this.config=y(f({},this.config),{userId:t}),yield this.initIfNeeded(),yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),yield this.resync()})}group(t,e){return h(this,null,function*(){yield this.initIfNeeded(),this.config.groupId=t,yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:e})}),yield this.resync()})}track(t,e){return h(this,null,function*(){if(yield this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})})),yield this.resync()})}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}getFlow(t){return h(this,null,function*(){return yield this.initIfNeeded(),this.flows.find(e=>e.id==t)})}getFlows(){return h(this,null,function*(){return yield this.initIfNeeded(),this.flows})}reload(){return h(this,null,function*(){X(),B(),yield this.refreshStateFromAPI(),this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,G(t))})})})}resync(){return h(this,null,function*(){this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,G(t))})})})}onStateChange(t){return h(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers.push(t)})}hasFailedToLoad(){return this.hasFailed}removeStateChangeHandler(t){return h(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(e=>e!==t)})}initIfNeeded(){return h(this,null,function*(){return this.initPromise!==null?this.initPromise:this.init(this.config)})}refreshStateFromAPI(){return h(this,null,function*(){let t=F(this.config);if(!g[t]){let e=this,i={set:function(o,n,l){if(o[n]){let r=o[n],d=l;JSON.stringify(r)!==JSON.stringify(d)&&e.triggerEventHandlers(d,r)}return o[n]=l,!0}};if(g[t]={refreshStateFromAPI:()=>h(this,null,function*(){}),rulesGraph:new C({graph:{},ruleOrder:[]}),flowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map,variables:{}},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockFlowStates(t);return}g[t].refreshStateFromAPI=o=>h(this,null,function*(){var r,d,p;if(this.config.__readOnly)return;let n=o||(yield this.fetch(`/flowStates?userId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&groupId=${encodeURIComponent(this.config.groupId)}`:""}`)),l=JSON.stringify(g[t].rulesGraph.rawGraphData)!==JSON.stringify((r=n.ruleGraph)==null?void 0:r.graph);g[t].rulesGraph=new C(n.ruleGraph,(p=(d=g[t])==null?void 0:d.rulesGraph)==null?void 0:p.getRegistry()),l&&this.flows.forEach(c=>{var v;if((v=n.ruleGraph)!=null&&v.graph[c.id]){let z=n.eligibleFlows.find(E=>E.flowSlug===c.id),Y=this.getGlobalState().previousFlows.get(c.id);c.resyncState(z),this.getGlobalState().onFlowStateChangeHandlers.forEach(E=>{E(c,Y),this.getGlobalState().previousFlows.set(c.id,G(c))})}}),n&&n.eligibleFlows?(n.eligibleFlows.forEach(c=>{g[t].flowStates[c.flowSlug]=c,this.flows.find(v=>v.id==c.flowSlug)||this.flows.push(new w({config:this.config,id:c.flowSlug}))}),this.hasFailed=!1):this.hasFailed=!0})}yield g[t].refreshStateFromAPI()})}mockFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var o,n,l;let i=JSON.parse(this.config.__flowConfigOverrides[e]);g[t].flowStates[e]={flowSlug:e,flowName:(o=i==null?void 0:i.name)!=null?o:e,flowType:(n=i==null?void 0:i.type)!=null?n:"CHECKLIST",data:y(f({},i),{steps:((l=i==null?void 0:i.steps)!=null?l:[]).map(r=>f({id:r.id,$state:{completed:!1,started:!1,visible:!0,blocked:!1}},r))}),$state:{currentStepId:null,currentStepIndex:-1,completed:!1,started:!1,skipped:!1,visible:!0}},this.flows.push(new w({config:this.config,id:e}))})}triggerEventHandlers(t,e){return h(this,null,function*(){t&&this.flows.forEach(i=>{i.id==e.flowSlug&&this.getGlobalState().onFlowStateChangeHandlers.forEach(o=>{let n=this.getGlobalState().previousFlows.get(i.id);i.resyncState(t),o(i,n),this.getGlobalState().previousFlows.set(i.id,G(i))})})})}};0&&(module.exports={Flow,Frigade});
|
|
2
|
+
var C=Object.defineProperty,B=Object.defineProperties,X=Object.getOwnPropertyDescriptor,z=Object.getOwnPropertyDescriptors,Y=Object.getOwnPropertyNames,R=Object.getOwnPropertySymbols;var P=Object.prototype.hasOwnProperty,Q=Object.prototype.propertyIsEnumerable;var $=(a,s,t)=>s in a?C(a,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[s]=t,p=(a,s)=>{for(var t in s||(s={}))P.call(s,t)&&$(a,t,s[t]);if(R)for(var t of R(s))Q.call(s,t)&&$(a,t,s[t]);return a},y=(a,s)=>B(a,z(s));var Z=(a,s)=>{for(var t in s)C(a,t,{get:s[t],enumerable:!0})},tt=(a,s,t,e)=>{if(s&&typeof s=="object"||typeof s=="function")for(let i of Y(s))!P.call(a,i)&&i!==t&&C(a,i,{get:()=>s[i],enumerable:!(e=X(s,i))||e.enumerable});return a};var et=a=>tt(C({},"__esModule",{value:!0}),a);var c=(a,s,t)=>new Promise((e,i)=>{var r=o=>{try{l(t.next(o))}catch(d){i(d)}},n=o=>{try{l(t.throw(o))}catch(d){i(d)}},l=o=>o.done?e(o.value):Promise.resolve(o.value).then(r,n);l((t=t.apply(a,s)).next())});var rt={};Z(rt,{Flow:()=>w,Frigade:()=>I});module.exports=et(rt);var A="0.2.20";var J=require("uuid");var f={};function G(a){var s,t;return`${a.__instanceId}-${a.apiKey}:${(s=a.userId)!=null?s:""}:${(t=a.groupId)!=null?t:""}`}var m=class{constructor(s){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:N(),__instanceId:Math.random().toString(12).substring(4)};let t=Object.fromEntries(Object.entries(s).filter(([e,i])=>i!=null));this.config=p(p({},this.config),t)}fetch(s,t){return c(this,null,function*(){return this.config.__readOnly?S():x(this.getAPIUrl(s),p(p({keepalive:!0},t!=null?t:{}),_(this.config.apiKey)))})}getAPIUrl(s){let t="/v1/public";return new URL(`${t}${s}`,this.config.apiUrl.replace(t,"")).toString()}getGlobalState(){let s=G(this.config);if(!f[s])throw new Error("Frigade has not yet been initialized");return f[s]}};var w=class extends m{constructor({config:t,id:e}){super(t);this._isVisible=!1;this.lastStepUpdate=new Map;this.id=e,this.init()}get isVisible(){return this._isVisible===!1?!1:this.getGlobalState().rulesGraph.isFlowVisible(this.id)}set isVisible(t){this._isVisible=t}reload(){this.init()}resyncState(t){var i,r;let e=t!=null?t:this.getStatefulFlow();this.rawData=e,this.title=(i=e==null?void 0:e.data)==null?void 0:i.title,this.subtitle=(r=e==null?void 0:e.data)==null?void 0:r.subtitle,this.isCompleted=e.$state.completed,this.isStarted=e.$state.started,this.isSkipped=e.$state.skipped,this._isVisible=e.$state.visible,e.data.steps.forEach((n,l)=>{var g;let o=this.initStepFromStatefulStep(n,l),d=(g=this.steps)==null?void 0:g.get(n.id);d&&(d.$state=o.$state)})}initStepFromStatefulStep(t,e){return y(p({},t),{flow:this,$state:y(p({},t.$state),{lastActionAt:t.$state.lastActionAt?new Date(t.$state.lastActionAt):void 0}),order:e})}init(){let t=this.getStatefulFlow();this.resyncState();let e=new Map;t.data.steps.forEach((i,r)=>{let n=this.initStepFromStatefulStep(i,r);n.start=l=>c(this,null,function*(){let o=this.steps.get(i.id);if(this.getCurrentStep().id===o.id&&o.$state.started)return;let d=u(this.getGlobalState().flowStates[this.id]);d.data.steps[o.order].$state.started=!0,d.data.steps[o.order].$state.lastActionAt=new Date,d.$state.lastActionAt=new Date,d.$state.currentStepId=o.id,d.$state.currentStepIndex=o.order,this.getGlobalState().flowStates[this.id]=d,this.resyncState(),o.$state.completed||(yield this.sendFlowStateToAPI(U,l,o.id))}),n.complete=l=>c(this,null,function*(){let o=this.steps.get(i.id);if(o.$state.completed)return;let g=this.getNumberOfCompletedSteps()+1==this.steps.size,h=u(this.getGlobalState().flowStates[this.id]);h.$state.started=!0,h.data.steps[o.order].$state.completed=!0,h.data.steps[o.order].$state.started=!0,h.data.steps[o.order].$state.lastActionAt=new Date,g||(h.$state.currentStepId=this.getStepByIndex(o.order+1).id,h.$state.currentStepIndex=o.order+1),g&&(h.$state.completed=!0),this.getGlobalState().flowStates[this.id]=h,this.resyncState(),g&&this.optimisticallyMarkFlowCompleted(),yield this.sendFlowStateToAPI(W,l,o.id)}),n.reset=()=>c(this,null,function*(){let l=this.steps.get(i.id);if(!l.$state.completed)return;let o=u(this.getGlobalState().flowStates[this.id]);o.data.steps[l.order].$state.started=!1,o.data.steps[l.order].$state.completed=!1,o.data.steps[l.order].$state.lastActionAt=void 0,this.getGlobalState().flowStates[this.id]=o,this.resyncState(),yield this.sendFlowStateToAPI(D,void 0,l.id)}),n.onStateChange=l=>{let o=d=>{if(d.id!==this.id)return;let g=d.steps.get(i.id),h=this.lastStepUpdate.get(l);(g.$state.completed!==(h==null?void 0:h.$state.completed)||g.$state.started!==(h==null?void 0:h.$state.started)||g.$state.visible!==(h==null?void 0:h.$state.visible)||g.$state.blocked!==(h==null?void 0:h.$state.blocked))&&(l(g,h!=null?h:u(g)),this.lastStepUpdate.set(l,u(g)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(l,o),this.getGlobalState().onFlowStateChangeHandlers.push(o)},n.removeStateChangeHandler=l=>{let o=this.getGlobalState().onStepStateChangeHandlerWrappers.get(l);o&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(d=>d!==o))},e.set(i.id,n)}),this.steps=e,this.getGlobalState().variables&&this.getGlobalState().variables[this.id]&&Object.keys(this.getGlobalState().variables[this.id]).length>0&&this.applyVariables(this.getGlobalState().variables[this.id])}start(t){return c(this,null,function*(){if(this.isStarted||this.isCompleted)return;let e=u(this.getGlobalState().flowStates[this.id]);e.$state.started=!0,this.getGlobalState().flowStates[this.id]=e,this.resyncState(),yield this.sendFlowStateToAPI(M,t)})}complete(t){return c(this,null,function*(){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),yield this.sendFlowStateToAPI(H,t))})}skip(t){return c(this,null,function*(){this.isSkipped||(this.optimisticallyMarkFlowSkipped(),yield this.sendFlowStateToAPI(k,t))})}forward(t){return c(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e?yield e.start(t):yield this.complete(t)})}back(t){return c(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&(yield e.start(t))})}restart(){return c(this,null,function*(){this.optimisticallyMarkFlowNotStarted(),yield this.sendFlowStateToAPI(L)})}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){var t;return(t=this.steps.get(this.getStatefulFlow().$state.currentStepId))!=null?t:this.steps.get(Array.from(this.steps.keys())[0])}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.completed).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.visible).length}onStateChange(t){let e=(i,r)=>{i.id===this.id&&(i.isCompleted!==(r==null?void 0:r.isCompleted)||i.isStarted!==(r==null?void 0:r.isStarted)||i.isSkipped!==(r==null?void 0:r.isSkipped)||i.isVisible!==(r==null?void 0:r.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(r==null?void 0:r.steps))&&t(i,r)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,e),this.getGlobalState().onFlowStateChangeHandlers.push(e)}removeStateChangeHandler(t){let e=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);e&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(i=>i!==e))}applyVariables(t){var i,r;let e=n=>{let l=n.match(/\${(.*?)}/g);return l&&l.forEach(o=>{let d=o.replace("${","").replace("}","");t[d]&&(n=n.replace(o,t[d]))}),n};this.title=e((i=this.title)!=null?i:""),this.subtitle=e((r=this.subtitle)!=null?r:""),this.steps.forEach(n=>{Object.keys(n).forEach(l=>{typeof n[l]=="string"&&(n[l]=e(n[l]))})}),this.getGlobalState().variables={},this.getGlobalState().variables[this.id]=t}getStatefulFlow(){return this.getGlobalState().flowStates[this.id]}optimisticallyMarkFlowCompleted(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.completed=!0,t.$state.started=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}optimisticallyMarkFlowNotStarted(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.completed=!1,t.$state.started=!1,t.$state.visible=!0,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}sendFlowStateToAPI(t,e,i){return c(this,null,function*(){let r=new Date;this.getGlobalState().lastSyncDate=r;let n=yield this.fetch("/flowStates",{method:"POST",body:JSON.stringify({userId:this.config.userId,groupId:this.config.groupId,flowSlug:this.id,stepId:i!=null?i:this.getCurrentStep().id,data:e?JSON.stringify(e):{},actionType:t,createdAt:r})});r<this.getGlobalState().lastSyncDate||(yield this.getGlobalState().refreshStateFromAPI(n))})}optimisticallyMarkFlowSkipped(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.skipped=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}register(t){this.getGlobalState().rulesGraph.register(this.id,i=>{let r=this.getGlobalState().previousFlows.get(this.id);(r==null?void 0:r._isVisible)!==i&&this.getGlobalState().onFlowStateChangeHandlers.forEach(n=>{n(this,r),this.getGlobalState().previousFlows.set(this.id,F(this))}),t==null||t(i)})}unregister(){this.getGlobalState().rulesGraph.unregister(this.id)}};var D="NOT_STARTED_STEP",H="COMPLETED_FLOW",k="SKIPPED_FLOW",M="STARTED_FLOW",L="NOT_STARTED_FLOW",W="COMPLETED_STEP",U="STARTED_STEP",K="frigade-guest-key",E="guest_",it="get-cache-",O="fr-js-";function F(a){return new w({config:a.config,id:a.id})}function u(a){return JSON.parse(JSON.stringify(a))}function _(a){return{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json","X-Frigade-SDK-Version":A,"X-Frigade-SDK-Platform":"Javascript"}}}function st(a){return b()?window.localStorage.getItem(`${O}${a}`):null}function at(a,s){b()&&window.localStorage.setItem(`${O}${a}`,s)}function j(){Object.keys(f).forEach(a=>{a.startsWith(it)&&delete f[a]})}function q(){b()&&Object.keys(window.localStorage).forEach(a=>{a.startsWith(O)&&window.localStorage.removeItem(a)})}var T=class{constructor(){this.queue=[];this.ttlInMS=500;this.cacheSize=5}push(s){let t=new Date;this.queue.length>=this.cacheSize&&this.queue.shift(),this.queue.push({call:s,time:t.getTime()})}hasIdenticalCall(s){let t=new Date;return this.queue=this.queue.filter(e=>t.getTime()-e.time<this.ttlInMS),this.queue.some(e=>e.call===s)}},V=new T;function x(a,s){return c(this,null,function*(){var e;if(typeof globalThis.fetch!="function")return S("- Attempted to call fetch() in an environment that doesn't support it.");if(b()&&s&&s.body&&s.method==="POST"){let i=`${a}${JSON.stringify((e=s.body)!=null?e:{})}`;if(V.hasIdenticalCall(i))return S();V.push(i)}let t;try{t=fetch(a,s),t=yield t}catch(i){return S(i)}if(!t)return S("Received an empty response");if(t.status>=400)return S(t.statusText);try{if(t.status===204)return S();let i;try{i=yield t.json()}catch(r){return S()}return i.error?S(i.error):i}catch(i){return S(i)}})}function S(a){return a&&console.log("Call to Frigade failed",a),{json:()=>({})}}function N(){if(b()){let a=st(K);return a||(a=`${E}${(0,J.v4)()}`,at(K,a)),a}}function b(){return typeof window!="undefined"&&typeof window.document!="undefined"&&typeof window.localStorage!="undefined"}var v=class{constructor(s){this.graph=new Map;this.registry=new Map;this.ruleOrder=[];var t,e;this.ruleOrder=(t=s==null?void 0:s.ruleOrder)!=null?t:[],this.ingestGraphData((e=s==null?void 0:s.graph)!=null?e:{})}ingestGraphData(s){this.graph=new Map(Object.entries(s)),this.fireCallbacks()}fireCallbacks(){for(let[s,t]of this.registry)typeof t=="function"&&t(this.isFlowVisible(s))}isFlowVisible(s){let t=this.graph.get(s);return t?t.visible===!1?!1:t.edges.length===0?!0:this.findRegisteredDescendant(s)==null:!0}register(s,t){this.registry.set(s,t!=null?t:()=>{}),this.fireCallbacks()}unregister(s){this.registry.delete(s),this.fireCallbacks()}getRegistry(){return this.registry}findRegisteredDescendant(s,t=s,e){let i=this.graph.get(s);if(i==null)return;if(this.registry.has(s)&&t!==s)return i;let r;if(i.edges.length>0)for(let n of i.edges){if(e!=null&&n.ruleId!==e)continue;let l=this.findRegisteredDescendant(n.head,t,e!=null?e:n.ruleId);if(l!=null&&l.visible){r=l;break}}return r}};var I=class extends m{constructor(t,e){super(p({apiKey:t},e));this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=()=>c(this,null,function*(){document.visibilityState==="visible"&&(yield this.refreshStateFromAPI())});this.init(this.config),b()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(b()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=G(this.config);f[t]&&(f[t].onFlowStateChangeHandlers=[])}}init(t){return c(this,null,function*(){return this.config=p(p({},this.config),t),this.initPromise=(()=>c(this,null,function*(){var e;this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(E))&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})),yield this.refreshStateFromAPI()}))(),this.initPromise})}identify(t,e){return c(this,null,function*(){this.config=y(p({},this.config),{userId:t}),yield this.initIfNeeded(),yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),yield this.resync()})}group(t,e){return c(this,null,function*(){yield this.initIfNeeded(),this.config.groupId=t,yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:e})}),yield this.resync()})}track(t,e){return c(this,null,function*(){if(yield this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})})),yield this.resync()})}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}getFlow(t){return c(this,null,function*(){return yield this.initIfNeeded(),this.flows.find(e=>e.id==t)})}getFlows(){return c(this,null,function*(){return yield this.initIfNeeded(),this.flows})}reload(){return c(this,null,function*(){q(),j(),yield this.refreshStateFromAPI(),this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,F(t))})})})}resync(){return c(this,null,function*(){this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,F(t))})})})}onStateChange(t){return c(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers.push(t)})}hasFailedToLoad(){return this.hasFailed}removeStateChangeHandler(t){return c(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(e=>e!==t)})}initIfNeeded(){return c(this,null,function*(){return this.initPromise!==null?this.initPromise:this.init(this.config)})}refreshStateFromAPI(){return c(this,null,function*(){let t=G(this.config);if(!f[t]){let e=this,i={set:function(r,n,l){if(r[n]){let o=r[n],d=l;JSON.stringify(o)!==JSON.stringify(d)&&e.triggerEventHandlers(d,o)}return r[n]=l,!0}};if(f[t]={refreshStateFromAPI:()=>c(this,null,function*(){}),rulesGraph:new v({graph:{},ruleOrder:[]}),flowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map,variables:{}},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockFlowStates(t);return}f[t].refreshStateFromAPI=r=>c(this,null,function*(){var l,o;if(this.config.__readOnly)return;let n=r||(yield this.fetch(`/flowStates?userId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&groupId=${encodeURIComponent(this.config.groupId)}`:""}`));f[t].rulesGraph.ingestGraphData((o=(l=n.ruleGraph)==null?void 0:l.graph)!=null?o:{}),n&&n.eligibleFlows?(n.eligibleFlows.forEach(d=>{f[t].flowStates[d.flowSlug]=d,this.flows.find(g=>g.id==d.flowSlug)||this.flows.push(new w({config:this.config,id:d.flowSlug}))}),this.hasFailed=!1):this.hasFailed=!0})}yield f[t].refreshStateFromAPI()})}mockFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var r,n,l;let i=JSON.parse(this.config.__flowConfigOverrides[e]);f[t].flowStates[e]={flowSlug:e,flowName:(r=i==null?void 0:i.name)!=null?r:e,flowType:(n=i==null?void 0:i.type)!=null?n:"CHECKLIST",data:y(p({},i),{steps:((l=i==null?void 0:i.steps)!=null?l:[]).map(o=>p({id:o.id,$state:{completed:!1,started:!1,visible:!0,blocked:!1}},o))}),$state:{currentStepId:null,currentStepIndex:-1,completed:!1,started:!1,skipped:!1,visible:!0}},this.flows.push(new w({config:this.config,id:e}))})}triggerEventHandlers(t,e){return c(this,null,function*(){t&&this.flows.forEach(i=>{i.id==e.flowSlug&&this.getGlobalState().onFlowStateChangeHandlers.forEach(r=>{let n=this.getGlobalState().previousFlows.get(i.id);i.resyncState(t),r(i,n),this.getGlobalState().previousFlows.set(i.id,F(i))})})})}};0&&(module.exports={Flow,Frigade});
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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/rules-graph.ts","../src/core/frigade.ts"],"sourcesContent":["export { Frigade } from './core/frigade'\nexport { Flow } from './core/flow'\nexport type { FlowStatus, FlowStep, FrigadeConfig, FlowType, TriggerType } from './core/types'\n","export const VERSION_NUMBER = '0.2.20'\n","import { VERSION_NUMBER } from '../core/version'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { frigadeGlobalState } from './state'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nconst GUEST_KEY = 'frigade-guest-key'\nexport const GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow({\n config: flow.config,\n id: flow.id,\n })\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n }\n}\n\nfunction setGlobalState(key: string, value: any) {\n frigadeGlobalState[key] = value\n}\n\nfunction getGlobalState(key: string): any {\n return frigadeGlobalState[key]\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nclass CallQueue {\n private queue: {\n call: string\n time: number\n }[] = []\n private readonly ttlInMS = 500\n private readonly cacheSize = 5\n\n public push(call: string) {\n const now = new Date()\n if (this.queue.length >= this.cacheSize) {\n this.queue.shift()\n }\n this.queue.push({\n call: call,\n time: now.getTime(),\n })\n }\n\n public hasIdenticalCall(call: string) {\n const now = new Date()\n this.queue = this.queue.filter((item) => now.getTime() - item.time < this.ttlInMS)\n return this.queue.some((item) => item.call === call)\n }\n}\n\nconst callQueue = new CallQueue()\n\nexport async function gracefulFetch(url: string, options: any) {\n if (typeof globalThis.fetch !== 'function') {\n return getEmptyResponse(\n \"- Attempted to call fetch() in an environment that doesn't support it.\"\n )\n }\n\n if (isWeb() && options && options.body && options.method === 'POST') {\n const lastCallDataKey = `${url}${JSON.stringify(options.body ?? {})}`\n if (callQueue.hasIdenticalCall(lastCallDataKey)) {\n return getEmptyResponse()\n }\n callQueue.push(lastCallDataKey)\n }\n\n let response\n try {\n response = fetch(url, options)\n response = await response\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n if (response.status === 204) {\n return getEmptyResponse()\n }\n\n let body\n try {\n body = await response.json()\n } catch (e) {\n return getEmptyResponse()\n }\n\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nexport function getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n\nexport function isWeb() {\n return (\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.localStorage !== 'undefined'\n )\n}\n","import { FlowStates, FlowStep, FrigadeConfig, StatefulFlow } from '../core/types'\nimport { Flow } from '../core/flow'\nimport { RulesGraph } from '../core/rules-graph'\n\nexport interface FrigadeGlobalState {\n refreshStateFromAPI: (overrideFlowStatesRaw?: FlowStates) => Promise<void>\n flowStates: Record<string, StatefulFlow>\n rulesGraph: RulesGraph\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 variables: Record<string, Record<string, any>>\n lastSyncDate?: Date\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.groupId ?? ''\n }`\n}\n","import { generateGuestId, getEmptyResponse, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../core/types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(12).substring(4),\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(this.getAPIUrl(path), {\n keepalive: true,\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n private getAPIUrl(path: string) {\n const pathPrefix = '/v1/public'\n const apiUrl = new URL(\n `${pathPrefix}${path}`,\n this.config.apiUrl.replace(pathPrefix, '')\n ).toString()\n\n return apiUrl\n }\n\n /**\n * @ignore\n */\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade has not yet been initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import {\n FlowActionType,\n FlowStateDTO,\n FlowStates,\n FlowStep,\n FrigadeConfig,\n StatefulFlow,\n StatefulStep,\n} from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n NOT_STARTED_STEP,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { Fetchable } from '../shared/fetchable'\nimport { RulesGraphRegistryCallback } from './rules-graph'\n\nexport class Flow extends Fetchable {\n /**\n * The Flow's ID.\n */\n public id: string\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The metadata of the Flow.\n * @ignore\n */\n public rawData: StatefulFlow\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 * @ignore\n */\n private _isVisible: boolean = false\n /**\n * Whether the Flow is visible to the user based on the current user/group's state.\n */\n get isVisible() {\n if (this._isVisible === false) {\n return false\n }\n\n return this.getGlobalState().rulesGraph.isFlowVisible(this.id)\n }\n set isVisible(visible: boolean) {\n this._isVisible = visible\n }\n\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n constructor({ config, id }: { config: FrigadeConfig; id: string }) {\n super(config)\n this.id = id\n this.init()\n }\n\n /**\n * Reload the Flow data from the server\n */\n reload() {\n this.init()\n }\n\n /**\n * @ignore\n */\n resyncState(overrideStatefulFlow?: StatefulFlow) {\n const statefulFlow = overrideStatefulFlow ?? this.getStatefulFlow()\n\n this.rawData = statefulFlow\n this.title = statefulFlow?.data?.title\n this.subtitle = statefulFlow?.data?.subtitle\n\n this.isCompleted = statefulFlow.$state.completed\n this.isStarted = statefulFlow.$state.started\n this.isSkipped = statefulFlow.$state.skipped\n this._isVisible = statefulFlow.$state.visible\n\n // Set\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n const existingStep = this.steps?.get(step.id)\n if (existingStep) {\n existingStep.$state = stepObj.$state\n }\n })\n }\n\n /**\n * @ignore\n */\n private initStepFromStatefulStep(step: StatefulStep, index: number) {\n return {\n ...step,\n flow: this,\n $state: {\n ...step.$state,\n lastActionAt: step.$state.lastActionAt ? new Date(step.$state.lastActionAt) : undefined,\n },\n order: index,\n } as Partial<FlowStep>\n }\n\n /**\n * @ignore\n */\n private init() {\n const statefulFlow = this.getStatefulFlow()\n\n this.resyncState()\n\n const newSteps = new Map<string, FlowStep>()\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.$state.started) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n copy.$state.lastActionAt = new Date()\n copy.$state.currentStepId = thisStep.id\n copy.$state.currentStepIndex = thisStep.order\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (!thisStep.$state.completed) {\n await this.sendFlowStateToAPI(STARTED_STEP, properties, thisStep.id)\n }\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (thisStep.$state.completed) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n const copy = clone(this.getGlobalState().flowStates[this.id])\n\n copy.$state.started = true\n copy.data.steps[thisStep.order].$state.completed = true\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n\n // If there are more index, advance current step\n if (!isLastStep) {\n copy.$state.currentStepId = this.getStepByIndex(thisStep.order + 1).id\n copy.$state.currentStepIndex = thisStep.order + 1\n }\n\n if (isLastStep) {\n copy.$state.completed = true\n }\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n await this.sendFlowStateToAPI(COMPLETED_STEP, properties, thisStep.id)\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.$state.completed) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = false\n copy.data.steps[thisStep.order].$state.completed = false\n copy.data.steps[thisStep.order].$state.lastActionAt = undefined\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(NOT_STARTED_STEP, undefined, thisStep.id)\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.$state.completed !== previousStep?.$state.completed ||\n thisStep.$state.started !== previousStep?.$state.started ||\n thisStep.$state.visible !== previousStep?.$state.visible ||\n thisStep.$state.blocked !== previousStep?.$state.blocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj as FlowStep)\n })\n this.steps = newSteps\n // Check if empty object\n if (\n this.getGlobalState().variables &&\n this.getGlobalState().variables[this.id] &&\n Object.keys(this.getGlobalState().variables[this.id]).length > 0\n ) {\n this.applyVariables(this.getGlobalState().variables[this.id])\n }\n }\n\n /**\n * Marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.started = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(STARTED_FLOW, properties)\n }\n\n /**\n * Marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n await this.sendFlowStateToAPI(COMPLETED_FLOW, properties)\n }\n\n /**\n * Marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n if (this.isSkipped) {\n return\n }\n this.optimisticallyMarkFlowSkipped()\n await this.sendFlowStateToAPI(SKIPPED_FLOW, properties)\n }\n\n /**\n * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: Record<string | number, any>) {\n const nextStep = this.getStepByIndex(this.getCurrentStepIndex() + 1)\n if (nextStep) {\n await nextStep.start(properties)\n } else {\n await this.complete(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: Record<string | number, any>) {\n const previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n this.optimisticallyMarkFlowNotStarted()\n await this.sendFlowStateToAPI(NOT_STARTED_FLOW)\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Gets current step\n */\n public getCurrentStep(): FlowStep {\n return (\n this.steps.get(this.getStatefulFlow().$state.currentStepId) ??\n this.steps.get(Array.from(this.steps.keys())[0])\n )\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.completed).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.visible).length\n }\n\n /**\n * @ignore\n */\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (flow.id === this.id) {\n if (\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 }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n /**\n * @ignore\n */\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n /**\n * @ignore\n */\n public applyVariables(variables: Record<string, any>) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n if (!variables[variable]) {\n return\n }\n str = str.replace(match, variables[variable])\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n this.steps.forEach((step) => {\n // Iterate over every string field in the step and replace variables\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n }\n })\n })\n\n this.getGlobalState().variables = {}\n this.getGlobalState().variables[this.id] = variables\n }\n\n /**\n * @ignore\n */\n private getStatefulFlow(): StatefulFlow {\n const userFlowStates = this.getGlobalState().flowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowCompleted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = true\n copy.$state.started = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowNotStarted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = false\n copy.$state.started = false\n copy.$state.visible = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n private async sendFlowStateToAPI(\n action: FlowActionType,\n data?: Record<string | number, any>,\n stepId?: string\n ) {\n const date = new Date()\n this.getGlobalState().lastSyncDate = date\n const flowStatesRaw: FlowStates = await this.fetch('/flowStates', {\n method: 'POST',\n body: JSON.stringify({\n userId: this.config.userId,\n groupId: this.config.groupId,\n flowSlug: this.id,\n stepId: stepId ?? this.getCurrentStep().id,\n data: data ? JSON.stringify(data) : {},\n actionType: action,\n createdAt: date,\n } as FlowStateDTO),\n })\n if (date < this.getGlobalState().lastSyncDate) {\n return\n }\n await this.getGlobalState().refreshStateFromAPI(flowStatesRaw)\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowSkipped() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.skipped = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n public register(callback?: RulesGraphRegistryCallback) {\n this.getGlobalState().rulesGraph.register(this.id, callback)\n }\n\n public unregister() {\n this.getGlobalState().rulesGraph.unregister(this.id)\n }\n}\n","import { RuleGraph } from './types'\n\nexport interface RulesGraphNode {\n visible: boolean\n edges: RulesGraphEdge[]\n}\n\nexport interface RulesGraphEdge {\n head: string\n ruleId: string\n}\n\nexport type RulesGraphRegistryCallback = (visible: boolean) => void\n\n// TODO: JSDoc this class\nexport class RulesGraph {\n private graph: Map<string, RulesGraphNode> = new Map()\n private readonly registry: Map<string, RulesGraphRegistryCallback> = new Map()\n private readonly _rawGraphData: RuleGraph\n private readonly ruleOrder: string[] = []\n public get rawGraphData() {\n return this._rawGraphData\n }\n\n constructor(graphData: RuleGraph, registry?: Map<string, RulesGraphRegistryCallback>) {\n this._rawGraphData = graphData\n if (registry) {\n this.registry = registry\n }\n this.ruleOrder = graphData?.ruleOrder ?? []\n this.ingestGraphData(graphData?.graph ?? {})\n }\n\n ingestGraphData(graphData: Record<string, RulesGraphNode>) {\n this.graph = new Map(Object.entries(graphData))\n\n this.fireCallbacks()\n }\n\n fireCallbacks() {\n for (const [flowId, callback] of this.registry) {\n if (typeof callback === 'function') {\n callback(this.isFlowVisible(flowId))\n }\n }\n }\n\n isFlowVisible(flowId: string) {\n const currentNode = this.graph.get(flowId)\n\n // Is the flow in the graph?\n // If not, it belongs to 0 rules and can carry on about its business\n if (!currentNode) {\n return true\n }\n\n if (currentNode.visible === false) {\n return false\n }\n\n // Does the flow have edges?\n // If not, it's the king of all flows, and it does what it wants\n if (currentNode.edges.length === 0) {\n return true\n }\n\n // Are any of the flow's descendants visible and in the registry already?\n const registeredDescendant = this.findRegisteredDescendant(flowId)\n\n // If so, this flow is not visible\n if (registeredDescendant != null) {\n return false\n }\n\n // Congrats! There are no conditions in the graph that disqualify this flow from being visible\n return true\n }\n\n register(flowId: string, callback?: RulesGraphRegistryCallback) {\n this.registry.set(flowId, callback)\n\n this.fireCallbacks()\n }\n\n unregister(flowId: string) {\n this.registry.delete(flowId)\n\n this.fireCallbacks()\n }\n\n getRegistry() {\n return this.registry\n }\n\n private findRegisteredDescendant(nodeId: string, originId = nodeId, ruleId?: string) {\n const node = this.graph.get(nodeId)\n\n if (node == null) {\n return undefined\n }\n\n if (this.registry.has(nodeId) && originId !== nodeId) {\n return node\n }\n\n let result = undefined\n\n if (node.edges.length > 0) {\n for (const edge of node.edges) {\n // If we went past the end of the rule, stop searching for this rule\n if (ruleId != null && edge.ruleId !== ruleId) {\n continue\n }\n\n const ancestor = this.findRegisteredDescendant(edge.head, originId, ruleId ?? edge.ruleId)\n\n if (ancestor != null && ancestor.visible) {\n result = ancestor\n break\n }\n }\n }\n\n return result\n }\n}\n","import { FlowStates, FrigadeConfig, StatefulFlow, StatefulStep } from './types'\nimport { clearCache, cloneFlow, GUEST_PREFIX, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/fetchable'\nimport { RulesGraph } from './rules-graph'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshStateFromAPI()\n }\n }\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n }\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\n */\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n if (this.config.userId && !this.config.userId?.startsWith(GUEST_PREFIX)) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n }),\n })\n }\n await this.refreshStateFromAPI()\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { ...this.config, userId }\n await this.initIfNeeded()\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.resync()\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = groupId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n properties,\n }),\n })\n await this.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n } else if (this.config.userId) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\n */\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n /**\n * Reload the current state of the flows by calling the Frigade API.\n * This will trigger all event handlers.\n */\n public async reload() {\n resetAllLocalStorage()\n clearCache()\n await this.refreshStateFromAPI()\n this.initPromise = null\n await this.init(this.config)\n // Trigger all event handlers\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n private async resync() {\n this.initPromise = null\n await this.init(this.config)\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @param handler\n */\n public async onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\n */\n public async removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n /**\n * @ignore\n */\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n /**\n * @ignore\n */\n private async refreshStateFromAPI(): 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 (target[key]) {\n const previousState = target[key] as StatefulFlow\n const newState = value as StatefulFlow\n if (JSON.stringify(previousState) !== JSON.stringify(newState)) {\n that.triggerEventHandlers(newState, previousState)\n }\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshStateFromAPI: async () => {},\n rulesGraph: new RulesGraph({\n graph: {},\n ruleOrder: [],\n }),\n flowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n variables: {},\n }\n\n if (this.config.__readOnly && this.config.__flowConfigOverrides) {\n this.mockFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshStateFromAPI = async (\n overrideFlowStateRaw?: FlowStates\n ) => {\n if (this.config.__readOnly) {\n return\n }\n\n const flowStateRaw: FlowStates = overrideFlowStateRaw\n ? overrideFlowStateRaw\n : await this.fetch(\n `/flowStates?userId=${encodeURIComponent(this.config.userId)}${\n this.config.groupId ? `&groupId=${encodeURIComponent(this.config.groupId)}` : ''\n }`\n )\n\n const hasRuleGraphChanged =\n JSON.stringify(frigadeGlobalState[globalStateKey].rulesGraph.rawGraphData) !==\n JSON.stringify(flowStateRaw.ruleGraph?.graph)\n\n frigadeGlobalState[globalStateKey].rulesGraph = new RulesGraph(\n flowStateRaw.ruleGraph,\n frigadeGlobalState[globalStateKey]?.rulesGraph?.getRegistry()\n )\n\n // Call all event handlers for the flows in the rulesgraph\n if (hasRuleGraphChanged) {\n this.flows.forEach((flow) => {\n if (flowStateRaw.ruleGraph?.graph[flow.id]) {\n const flowState = flowStateRaw.eligibleFlows.find((f) => f.flowSlug === flow.id)\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(flowState)\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n\n if (flowStateRaw && flowStateRaw.eligibleFlows) {\n flowStateRaw.eligibleFlows.forEach((statefulFlow) => {\n frigadeGlobalState[globalStateKey].flowStates[statefulFlow.flowSlug] = statefulFlow\n if (!this.flows.find((flow) => flow.id == statefulFlow.flowSlug)) {\n this.flows.push(\n new Flow({\n config: this.config,\n id: statefulFlow.flowSlug,\n })\n )\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshStateFromAPI()\n }\n\n /**\n * @ignore\n */\n private mockFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n const parsed = JSON.parse(this.config.__flowConfigOverrides[flowId])\n frigadeGlobalState[globalStateKey].flowStates[flowId] = {\n flowSlug: flowId,\n flowName: parsed?.name ?? flowId,\n flowType: parsed?.type ?? 'CHECKLIST',\n data: {\n ...parsed,\n steps: (parsed?.steps ?? []).map((step: any): StatefulStep => {\n return {\n id: step.id,\n $state: {\n completed: false,\n started: false,\n visible: true,\n blocked: false,\n },\n ...step,\n }\n }),\n },\n $state: {\n currentStepId: null,\n currentStepIndex: -1,\n completed: false,\n started: false,\n skipped: false,\n visible: true,\n },\n } as StatefulFlow\n\n this.flows.push(\n new Flow({\n config: this.config,\n id: flowId,\n })\n )\n })\n }\n\n /**\n * @ignore\n */\n private async triggerEventHandlers(newState: StatefulFlow, previousState?: StatefulFlow) {\n if (newState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousState.flowSlug) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(newState)\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_uuid","frigadeGlobalState","getGlobalStateKey","internalConfig","_a","_b","Fetchable","config","generateGuestId","filteredConfig","_","v","__spreadValues","path","options","__async","getEmptyResponse","gracefulFetch","getHeaders","pathPrefix","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","id","visible","overrideStatefulFlow","_a","_b","statefulFlow","step","index","stepObj","existingStep","__spreadProps","__spreadValues","newSteps","properties","__async","thisStep","copy","clone","STARTED_STEP","isLastStep","COMPLETED_STEP","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","h","STARTED_FLOW","COMPLETED_FLOW","SKIPPED_FLOW","nextStep","NOT_STARTED_FLOW","currentStep","previousFlow","variables","replaceVariables","str","matches","match","variable","key","action","data","stepId","date","flowStatesRaw","callback","NOT_STARTED_STEP","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","LOCAL_STORAGE_PREFIX","cloneFlow","flow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","clearCache","frigadeGlobalState","key","GET_CACHE_PREFIX","resetAllLocalStorage","isWeb","LOCAL_STORAGE_PREFIX","CallQueue","call","now","item","callQueue","gracefulFetch","url","options","__async","_a","getEmptyResponse","lastCallDataKey","response","error","body","e","generateGuestId","guestId","getLocalStorage","GUEST_KEY","GUEST_PREFIX","uuidv4","setLocalStorage","isWeb","RulesGraph","graphData","registry","_a","_b","flowId","callback","currentNode","nodeId","originId","ruleId","node","result","edge","ancestor","Frigade","Fetchable","apiKey","config","__spreadValues","__async","isWeb","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","__spreadProps","groupId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","that","validator","target","key","value","previousState","newState","RulesGraph","overrideFlowStateRaw","_b","_c","flowStateRaw","hasRuleGraphChanged","flowState","f","statefulFlow","Flow","parsed","step"]}
|
|
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/rules-graph.ts","../src/core/frigade.ts"],"sourcesContent":["export { Frigade } from './core/frigade'\nexport { Flow } from './core/flow'\nexport type { FlowStatus, FlowStep, FrigadeConfig, FlowType, TriggerType } from './core/types'\nexport type { RulesGraphRegistryCallback } from './core/rules-graph'\n","export const VERSION_NUMBER = '0.2.20'\n","import { VERSION_NUMBER } from '../core/version'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { frigadeGlobalState } from './state'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nconst GUEST_KEY = 'frigade-guest-key'\nexport const GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow({\n config: flow.config,\n id: flow.id,\n })\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n }\n}\n\nfunction setGlobalState(key: string, value: any) {\n frigadeGlobalState[key] = value\n}\n\nfunction getGlobalState(key: string): any {\n return frigadeGlobalState[key]\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nclass CallQueue {\n private queue: {\n call: string\n time: number\n }[] = []\n private readonly ttlInMS = 500\n private readonly cacheSize = 5\n\n public push(call: string) {\n const now = new Date()\n if (this.queue.length >= this.cacheSize) {\n this.queue.shift()\n }\n this.queue.push({\n call: call,\n time: now.getTime(),\n })\n }\n\n public hasIdenticalCall(call: string) {\n const now = new Date()\n this.queue = this.queue.filter((item) => now.getTime() - item.time < this.ttlInMS)\n return this.queue.some((item) => item.call === call)\n }\n}\n\nconst callQueue = new CallQueue()\n\nexport async function gracefulFetch(url: string, options: any) {\n if (typeof globalThis.fetch !== 'function') {\n return getEmptyResponse(\n \"- Attempted to call fetch() in an environment that doesn't support it.\"\n )\n }\n\n if (isWeb() && options && options.body && options.method === 'POST') {\n const lastCallDataKey = `${url}${JSON.stringify(options.body ?? {})}`\n if (callQueue.hasIdenticalCall(lastCallDataKey)) {\n return getEmptyResponse()\n }\n callQueue.push(lastCallDataKey)\n }\n\n let response\n try {\n response = fetch(url, options)\n response = await response\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n if (response.status === 204) {\n return getEmptyResponse()\n }\n\n let body\n try {\n body = await response.json()\n } catch (e) {\n return getEmptyResponse()\n }\n\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nexport function getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n\nexport function isWeb() {\n return (\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.localStorage !== 'undefined'\n )\n}\n","import { FlowStates, FlowStep, FrigadeConfig, StatefulFlow } from '../core/types'\nimport { Flow } from '../core/flow'\nimport { RulesGraph } from '../core/rules-graph'\n\nexport interface FrigadeGlobalState {\n refreshStateFromAPI: (overrideFlowStatesRaw?: FlowStates) => Promise<void>\n flowStates: Record<string, StatefulFlow>\n rulesGraph: RulesGraph\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 variables: Record<string, Record<string, any>>\n lastSyncDate?: Date\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.groupId ?? ''\n }`\n}\n","import { generateGuestId, getEmptyResponse, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../core/types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(12).substring(4),\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(this.getAPIUrl(path), {\n keepalive: true,\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n private getAPIUrl(path: string) {\n const pathPrefix = '/v1/public'\n const apiUrl = new URL(\n `${pathPrefix}${path}`,\n this.config.apiUrl.replace(pathPrefix, '')\n ).toString()\n\n return apiUrl\n }\n\n /**\n * @ignore\n */\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade has not yet been initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import {\n FlowActionType,\n FlowStateDTO,\n FlowStates,\n FlowStep,\n FrigadeConfig,\n StatefulFlow,\n StatefulStep,\n} from './types'\nimport {\n clone,\n cloneFlow,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n NOT_STARTED_STEP,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { Fetchable } from '../shared/fetchable'\nimport { RulesGraphRegistryCallback } from './rules-graph'\n\nexport class Flow extends Fetchable {\n /**\n * The Flow's ID.\n */\n public id: string\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The metadata of the Flow.\n * @ignore\n */\n public rawData: StatefulFlow\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 * @ignore\n */\n private _isVisible: boolean = false\n /**\n * Whether the Flow is visible to the user based on the current user/group's state.\n */\n get isVisible() {\n if (this._isVisible === false) {\n return false\n }\n\n return this.getGlobalState().rulesGraph.isFlowVisible(this.id)\n }\n set isVisible(visible: boolean) {\n this._isVisible = visible\n }\n\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n constructor({ config, id }: { config: FrigadeConfig; id: string }) {\n super(config)\n this.id = id\n this.init()\n }\n\n /**\n * Reload the Flow data from the server\n */\n reload() {\n this.init()\n }\n\n /**\n * @ignore\n */\n resyncState(overrideStatefulFlow?: StatefulFlow) {\n const statefulFlow = overrideStatefulFlow ?? this.getStatefulFlow()\n\n this.rawData = statefulFlow\n this.title = statefulFlow?.data?.title\n this.subtitle = statefulFlow?.data?.subtitle\n\n this.isCompleted = statefulFlow.$state.completed\n this.isStarted = statefulFlow.$state.started\n this.isSkipped = statefulFlow.$state.skipped\n this._isVisible = statefulFlow.$state.visible\n\n // Set\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n const existingStep = this.steps?.get(step.id)\n if (existingStep) {\n existingStep.$state = stepObj.$state\n }\n })\n }\n\n /**\n * @ignore\n */\n private initStepFromStatefulStep(step: StatefulStep, index: number) {\n return {\n ...step,\n flow: this,\n $state: {\n ...step.$state,\n lastActionAt: step.$state.lastActionAt ? new Date(step.$state.lastActionAt) : undefined,\n },\n order: index,\n } as Partial<FlowStep>\n }\n\n /**\n * @ignore\n */\n private init() {\n const statefulFlow = this.getStatefulFlow()\n\n this.resyncState()\n\n const newSteps = new Map<string, FlowStep>()\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.$state.started) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n copy.$state.lastActionAt = new Date()\n copy.$state.currentStepId = thisStep.id\n copy.$state.currentStepIndex = thisStep.order\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (!thisStep.$state.completed) {\n await this.sendFlowStateToAPI(STARTED_STEP, properties, thisStep.id)\n }\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (thisStep.$state.completed) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n const copy = clone(this.getGlobalState().flowStates[this.id])\n\n copy.$state.started = true\n copy.data.steps[thisStep.order].$state.completed = true\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n\n // If there are more index, advance current step\n if (!isLastStep) {\n copy.$state.currentStepId = this.getStepByIndex(thisStep.order + 1).id\n copy.$state.currentStepIndex = thisStep.order + 1\n }\n\n if (isLastStep) {\n copy.$state.completed = true\n }\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n await this.sendFlowStateToAPI(COMPLETED_STEP, properties, thisStep.id)\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.$state.completed) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = false\n copy.data.steps[thisStep.order].$state.completed = false\n copy.data.steps[thisStep.order].$state.lastActionAt = undefined\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(NOT_STARTED_STEP, undefined, thisStep.id)\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.$state.completed !== previousStep?.$state.completed ||\n thisStep.$state.started !== previousStep?.$state.started ||\n thisStep.$state.visible !== previousStep?.$state.visible ||\n thisStep.$state.blocked !== previousStep?.$state.blocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj as FlowStep)\n })\n this.steps = newSteps\n // Check if empty object\n if (\n this.getGlobalState().variables &&\n this.getGlobalState().variables[this.id] &&\n Object.keys(this.getGlobalState().variables[this.id]).length > 0\n ) {\n this.applyVariables(this.getGlobalState().variables[this.id])\n }\n }\n\n /**\n * Marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.started = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(STARTED_FLOW, properties)\n }\n\n /**\n * Marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n await this.sendFlowStateToAPI(COMPLETED_FLOW, properties)\n }\n\n /**\n * Marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n if (this.isSkipped) {\n return\n }\n this.optimisticallyMarkFlowSkipped()\n await this.sendFlowStateToAPI(SKIPPED_FLOW, properties)\n }\n\n /**\n * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: Record<string | number, any>) {\n const nextStep = this.getStepByIndex(this.getCurrentStepIndex() + 1)\n if (nextStep) {\n await nextStep.start(properties)\n } else {\n await this.complete(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: Record<string | number, any>) {\n const previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n this.optimisticallyMarkFlowNotStarted()\n await this.sendFlowStateToAPI(NOT_STARTED_FLOW)\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Gets current step\n */\n public getCurrentStep(): FlowStep {\n return (\n this.steps.get(this.getStatefulFlow().$state.currentStepId) ??\n this.steps.get(Array.from(this.steps.keys())[0])\n )\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.completed).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.visible).length\n }\n\n /**\n * @ignore\n */\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (flow.id === this.id) {\n if (\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 }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n /**\n * @ignore\n */\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n /**\n * @ignore\n */\n public applyVariables(variables: Record<string, any>) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n if (!variables[variable]) {\n return\n }\n str = str.replace(match, variables[variable])\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n this.steps.forEach((step) => {\n // Iterate over every string field in the step and replace variables\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n }\n })\n })\n\n this.getGlobalState().variables = {}\n this.getGlobalState().variables[this.id] = variables\n }\n\n /**\n * @ignore\n */\n private getStatefulFlow(): StatefulFlow {\n const userFlowStates = this.getGlobalState().flowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowCompleted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = true\n copy.$state.started = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowNotStarted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = false\n copy.$state.started = false\n copy.$state.visible = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n private async sendFlowStateToAPI(\n action: FlowActionType,\n data?: Record<string | number, any>,\n stepId?: string\n ) {\n const date = new Date()\n this.getGlobalState().lastSyncDate = date\n const flowStatesRaw: FlowStates = await this.fetch('/flowStates', {\n method: 'POST',\n body: JSON.stringify({\n userId: this.config.userId,\n groupId: this.config.groupId,\n flowSlug: this.id,\n stepId: stepId ?? this.getCurrentStep().id,\n data: data ? JSON.stringify(data) : {},\n actionType: action,\n createdAt: date,\n } as FlowStateDTO),\n })\n if (date < this.getGlobalState().lastSyncDate) {\n return\n }\n await this.getGlobalState().refreshStateFromAPI(flowStatesRaw)\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowSkipped() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.skipped = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n public register(callback?: RulesGraphRegistryCallback) {\n const globalState = this.getGlobalState()\n\n globalState.rulesGraph.register(this.id, (visible) => {\n const prevFlow = this.getGlobalState().previousFlows.get(this.id)\n\n if (prevFlow?._isVisible !== visible) {\n // TODO: Store these in a hash so we can grab this flow's handler and call it\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n handler(this, prevFlow)\n this.getGlobalState().previousFlows.set(this.id, cloneFlow(this))\n })\n }\n\n callback?.(visible)\n })\n }\n\n public unregister() {\n this.getGlobalState().rulesGraph.unregister(this.id)\n }\n}\n","import { RulesGraphData } from './types'\n\nexport interface RulesGraphNode {\n visible: boolean\n edges: RulesGraphEdge[]\n}\n\nexport interface RulesGraphEdge {\n head: string\n ruleId: string\n}\n\nexport type RulesGraphRegistryCallback = (visible: boolean) => void\n\n// TODO: JSDoc this class\nexport class RulesGraph {\n private graph: Map<string, RulesGraphNode> = new Map()\n private readonly registry: Map<string, RulesGraphRegistryCallback> = new Map()\n private readonly ruleOrder: string[] = []\n\n constructor(graphData: RulesGraphData) {\n this.ruleOrder = graphData?.ruleOrder ?? []\n this.ingestGraphData(graphData?.graph ?? {})\n }\n\n ingestGraphData(graphData: Record<string, RulesGraphNode>) {\n this.graph = new Map(Object.entries(graphData))\n\n this.fireCallbacks()\n }\n\n fireCallbacks() {\n for (const [flowId, callback] of this.registry) {\n if (typeof callback === 'function') {\n callback(this.isFlowVisible(flowId))\n }\n }\n }\n\n isFlowVisible(flowId: string) {\n const currentNode = this.graph.get(flowId)\n\n // Is the flow in the graph?\n // If not, it belongs to 0 rules and can carry on about its business\n if (!currentNode) {\n return true\n }\n\n if (currentNode.visible === false) {\n return false\n }\n\n // Does the flow have edges?\n // If not, it's the king of all flows, and it does what it wants\n if (currentNode.edges.length === 0) {\n return true\n }\n\n // Are any of the flow's descendants visible and in the registry already?\n const registeredDescendant = this.findRegisteredDescendant(flowId)\n\n // If so, this flow is not visible\n if (registeredDescendant != null) {\n return false\n }\n\n // Congrats! There are no conditions in the graph that disqualify this flow from being visible\n return true\n }\n\n register(flowId: string, callback?: RulesGraphRegistryCallback) {\n this.registry.set(flowId, callback ?? (() => {}))\n\n this.fireCallbacks()\n }\n\n unregister(flowId: string) {\n this.registry.delete(flowId)\n\n this.fireCallbacks()\n }\n\n getRegistry() {\n return this.registry\n }\n\n private findRegisteredDescendant(nodeId: string, originId = nodeId, ruleId?: string) {\n const node = this.graph.get(nodeId)\n\n if (node == null) {\n return undefined\n }\n\n if (this.registry.has(nodeId) && originId !== nodeId) {\n return node\n }\n\n let result = undefined\n\n if (node.edges.length > 0) {\n for (const edge of node.edges) {\n // If we went past the end of the rule, stop searching for this rule\n if (ruleId != null && edge.ruleId !== ruleId) {\n continue\n }\n\n const ancestor = this.findRegisteredDescendant(edge.head, originId, ruleId ?? edge.ruleId)\n\n if (ancestor != null && ancestor.visible) {\n result = ancestor\n break\n }\n }\n }\n\n return result\n }\n}\n","import { FlowStates, FrigadeConfig, StatefulFlow, StatefulStep } from './types'\nimport { clearCache, cloneFlow, GUEST_PREFIX, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/fetchable'\nimport { RulesGraph } from './rules-graph'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshStateFromAPI()\n }\n }\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n }\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\n */\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n if (this.config.userId && !this.config.userId?.startsWith(GUEST_PREFIX)) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n }),\n })\n }\n await this.refreshStateFromAPI()\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { ...this.config, userId }\n await this.initIfNeeded()\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.resync()\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = groupId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n properties,\n }),\n })\n await this.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n } else if (this.config.userId) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\n */\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n /**\n * Reload the current state of the flows by calling the Frigade API.\n * This will trigger all event handlers.\n */\n public async reload() {\n resetAllLocalStorage()\n clearCache()\n await this.refreshStateFromAPI()\n this.initPromise = null\n await this.init(this.config)\n // Trigger all event handlers\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n private async resync() {\n this.initPromise = null\n await this.init(this.config)\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @param handler\n */\n public async onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\n */\n public async removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n /**\n * @ignore\n */\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n /**\n * @ignore\n */\n private async refreshStateFromAPI(): 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 (target[key]) {\n const previousState = target[key] as StatefulFlow\n const newState = value as StatefulFlow\n if (JSON.stringify(previousState) !== JSON.stringify(newState)) {\n that.triggerEventHandlers(newState, previousState)\n }\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshStateFromAPI: async () => {},\n rulesGraph: new RulesGraph({\n graph: {},\n ruleOrder: [],\n }),\n flowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n variables: {},\n }\n\n if (this.config.__readOnly && this.config.__flowConfigOverrides) {\n this.mockFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshStateFromAPI = async (\n overrideFlowStateRaw?: FlowStates\n ) => {\n if (this.config.__readOnly) {\n return\n }\n\n const flowStateRaw: FlowStates = overrideFlowStateRaw\n ? overrideFlowStateRaw\n : await this.fetch(\n `/flowStates?userId=${encodeURIComponent(this.config.userId)}${\n this.config.groupId ? `&groupId=${encodeURIComponent(this.config.groupId)}` : ''\n }`\n )\n\n // TODO: should this also take in order and check if it has changed?\n frigadeGlobalState[globalStateKey].rulesGraph.ingestGraphData(\n flowStateRaw.ruleGraph?.graph ?? {}\n )\n\n if (flowStateRaw && flowStateRaw.eligibleFlows) {\n flowStateRaw.eligibleFlows.forEach((statefulFlow) => {\n frigadeGlobalState[globalStateKey].flowStates[statefulFlow.flowSlug] = statefulFlow\n if (!this.flows.find((flow) => flow.id == statefulFlow.flowSlug)) {\n this.flows.push(\n new Flow({\n config: this.config,\n id: statefulFlow.flowSlug,\n })\n )\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshStateFromAPI()\n }\n\n /**\n * @ignore\n */\n private mockFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n const parsed = JSON.parse(this.config.__flowConfigOverrides[flowId])\n frigadeGlobalState[globalStateKey].flowStates[flowId] = {\n flowSlug: flowId,\n flowName: parsed?.name ?? flowId,\n flowType: parsed?.type ?? 'CHECKLIST',\n data: {\n ...parsed,\n steps: (parsed?.steps ?? []).map((step: any): StatefulStep => {\n return {\n id: step.id,\n $state: {\n completed: false,\n started: false,\n visible: true,\n blocked: false,\n },\n ...step,\n }\n }),\n },\n $state: {\n currentStepId: null,\n currentStepIndex: -1,\n completed: false,\n started: false,\n skipped: false,\n visible: true,\n },\n } as StatefulFlow\n\n this.flows.push(\n new Flow({\n config: this.config,\n id: flowId,\n })\n )\n })\n }\n\n /**\n * @ignore\n */\n private async triggerEventHandlers(newState: StatefulFlow, previousState?: StatefulFlow) {\n if (newState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousState.flowSlug) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(newState)\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_uuid","frigadeGlobalState","getGlobalStateKey","internalConfig","_a","_b","Fetchable","config","generateGuestId","filteredConfig","_","v","__spreadValues","path","options","__async","getEmptyResponse","gracefulFetch","getHeaders","pathPrefix","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","id","visible","overrideStatefulFlow","_a","_b","statefulFlow","step","index","stepObj","existingStep","__spreadProps","__spreadValues","newSteps","properties","__async","thisStep","copy","clone","STARTED_STEP","isLastStep","COMPLETED_STEP","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","h","STARTED_FLOW","COMPLETED_FLOW","SKIPPED_FLOW","nextStep","NOT_STARTED_FLOW","currentStep","previousFlow","variables","replaceVariables","str","matches","match","variable","key","action","data","stepId","date","flowStatesRaw","callback","prevFlow","cloneFlow","NOT_STARTED_STEP","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","LOCAL_STORAGE_PREFIX","cloneFlow","flow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","clearCache","frigadeGlobalState","key","GET_CACHE_PREFIX","resetAllLocalStorage","isWeb","LOCAL_STORAGE_PREFIX","CallQueue","call","now","item","callQueue","gracefulFetch","url","options","__async","_a","getEmptyResponse","lastCallDataKey","response","error","body","e","generateGuestId","guestId","getLocalStorage","GUEST_KEY","GUEST_PREFIX","uuidv4","setLocalStorage","isWeb","RulesGraph","graphData","_a","_b","flowId","callback","currentNode","nodeId","originId","ruleId","node","result","edge","ancestor","Frigade","Fetchable","apiKey","config","__spreadValues","__async","isWeb","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","__spreadProps","groupId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","that","validator","target","key","value","previousState","newState","RulesGraph","overrideFlowStateRaw","_b","flowStateRaw","statefulFlow","Flow","_c","parsed","step"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,10 +10,8 @@ type RulesGraphRegistryCallback = (visible: boolean) => void;
|
|
|
10
10
|
declare class RulesGraph {
|
|
11
11
|
private graph;
|
|
12
12
|
private readonly registry;
|
|
13
|
-
private readonly _rawGraphData;
|
|
14
13
|
private readonly ruleOrder;
|
|
15
|
-
|
|
16
|
-
constructor(graphData: RuleGraph, registry?: Map<string, RulesGraphRegistryCallback>);
|
|
14
|
+
constructor(graphData: RulesGraphData);
|
|
17
15
|
ingestGraphData(graphData: Record<string, RulesGraphNode>): void;
|
|
18
16
|
fireCallbacks(): void;
|
|
19
17
|
isFlowVisible(flowId: string): boolean;
|
|
@@ -432,14 +430,14 @@ interface StatefulFlow {
|
|
|
432
430
|
lastActionAt?: Date;
|
|
433
431
|
};
|
|
434
432
|
}
|
|
435
|
-
interface
|
|
433
|
+
interface RulesGraphData {
|
|
436
434
|
ruleOrder: string[];
|
|
437
435
|
graph: Record<string, RulesGraphNode>;
|
|
438
436
|
}
|
|
439
437
|
interface FlowStates {
|
|
440
438
|
eligibleFlows: StatefulFlow[];
|
|
441
439
|
ineligibleFlows: string[];
|
|
442
|
-
ruleGraph?:
|
|
440
|
+
ruleGraph?: RulesGraphData;
|
|
443
441
|
}
|
|
444
442
|
declare enum FlowType {
|
|
445
443
|
ANNOUNCEMENT = "ANNOUNCEMENT",
|
|
@@ -547,4 +545,4 @@ declare class Frigade extends Fetchable {
|
|
|
547
545
|
private triggerEventHandlers;
|
|
548
546
|
}
|
|
549
547
|
|
|
550
|
-
export { Flow, FlowStatus, FlowStep, FlowType, Frigade, FrigadeConfig, TriggerType };
|
|
548
|
+
export { Flow, FlowStatus, FlowStep, FlowType, Frigade, FrigadeConfig, RulesGraphRegistryCallback, TriggerType };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var X=Object.defineProperty,z=Object.defineProperties;var Y=Object.getOwnPropertyDescriptors;var $=Object.getOwnPropertySymbols;var Q=Object.prototype.hasOwnProperty,Z=Object.prototype.propertyIsEnumerable;var P=(a,s,t)=>s in a?X(a,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[s]=t,f=(a,s)=>{for(var t in s||(s={}))Q.call(s,t)&&P(a,t,s[t]);if($)for(var t of $(s))Z.call(s,t)&&P(a,t,s[t]);return a},y=(a,s)=>z(a,Y(s));var h=(a,s,t)=>new Promise((e,i)=>{var o=r=>{try{l(t.next(r))}catch(d){i(d)}},n=r=>{try{l(t.throw(r))}catch(d){i(d)}},l=r=>r.done?e(r.value):Promise.resolve(r.value).then(o,n);l((t=t.apply(a,s)).next())});var _="0.2.20";import{v4 as tt}from"uuid";var g={};function F(a){var s,t;return`${a.__instanceId}-${a.apiKey}:${(s=a.userId)!=null?s:""}:${(t=a.groupId)!=null?t:""}`}var m=class{constructor(s){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:N(),__instanceId:Math.random().toString(12).substring(4)};let t=Object.fromEntries(Object.entries(s).filter(([e,i])=>i!=null));this.config=f(f({},this.config),t)}fetch(s,t){return h(this,null,function*(){return this.config.__readOnly?S():x(this.getAPIUrl(s),f(f({keepalive:!0},t!=null?t:{}),A(this.config.apiKey)))})}getAPIUrl(s){let t="/v1/public";return new URL(`${t}${s}`,this.config.apiUrl.replace(t,"")).toString()}getGlobalState(){let s=F(this.config);if(!g[s])throw new Error("Frigade has not yet been initialized");return g[s]}};var w=class extends m{constructor({config:t,id:e}){super(t);this._isVisible=!1;this.lastStepUpdate=new Map;this.id=e,this.init()}get isVisible(){return this._isVisible===!1?!1:this.getGlobalState().rulesGraph.isFlowVisible(this.id)}set isVisible(t){this._isVisible=t}reload(){this.init()}resyncState(t){var i,o;let e=t!=null?t:this.getStatefulFlow();this.rawData=e,this.title=(i=e==null?void 0:e.data)==null?void 0:i.title,this.subtitle=(o=e==null?void 0:e.data)==null?void 0:o.subtitle,this.isCompleted=e.$state.completed,this.isStarted=e.$state.started,this.isSkipped=e.$state.skipped,this._isVisible=e.$state.visible,e.data.steps.forEach((n,l)=>{var p;let r=this.initStepFromStatefulStep(n,l),d=(p=this.steps)==null?void 0:p.get(n.id);d&&(d.$state=r.$state)})}initStepFromStatefulStep(t,e){return y(f({},t),{flow:this,$state:y(f({},t.$state),{lastActionAt:t.$state.lastActionAt?new Date(t.$state.lastActionAt):void 0}),order:e})}init(){let t=this.getStatefulFlow();this.resyncState();let e=new Map;t.data.steps.forEach((i,o)=>{let n=this.initStepFromStatefulStep(i,o);n.start=l=>h(this,null,function*(){let r=this.steps.get(i.id);if(this.getCurrentStep().id===r.id&&r.$state.started)return;let d=u(this.getGlobalState().flowStates[this.id]);d.data.steps[r.order].$state.started=!0,d.data.steps[r.order].$state.lastActionAt=new Date,d.$state.lastActionAt=new Date,d.$state.currentStepId=r.id,d.$state.currentStepIndex=r.order,this.getGlobalState().flowStates[this.id]=d,this.resyncState(),r.$state.completed||(yield this.sendFlowStateToAPI(U,l,r.id))}),n.complete=l=>h(this,null,function*(){let r=this.steps.get(i.id);if(r.$state.completed)return;let p=this.getNumberOfCompletedSteps()+1==this.steps.size,c=u(this.getGlobalState().flowStates[this.id]);c.$state.started=!0,c.data.steps[r.order].$state.completed=!0,c.data.steps[r.order].$state.started=!0,c.data.steps[r.order].$state.lastActionAt=new Date,p||(c.$state.currentStepId=this.getStepByIndex(r.order+1).id,c.$state.currentStepIndex=r.order+1),p&&(c.$state.completed=!0),this.getGlobalState().flowStates[this.id]=c,this.resyncState(),p&&this.optimisticallyMarkFlowCompleted(),yield this.sendFlowStateToAPI(W,l,r.id)}),n.reset=()=>h(this,null,function*(){let l=this.steps.get(i.id);if(!l.$state.completed)return;let r=u(this.getGlobalState().flowStates[this.id]);r.data.steps[l.order].$state.started=!1,r.data.steps[l.order].$state.completed=!1,r.data.steps[l.order].$state.lastActionAt=void 0,this.getGlobalState().flowStates[this.id]=r,this.resyncState(),yield this.sendFlowStateToAPI(k,void 0,l.id)}),n.onStateChange=l=>{let r=d=>{if(d.id!==this.id)return;let p=d.steps.get(i.id),c=this.lastStepUpdate.get(l);(p.$state.completed!==(c==null?void 0:c.$state.completed)||p.$state.started!==(c==null?void 0:c.$state.started)||p.$state.visible!==(c==null?void 0:c.$state.visible)||p.$state.blocked!==(c==null?void 0:c.$state.blocked))&&(l(p,c!=null?c:u(p)),this.lastStepUpdate.set(l,u(p)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(l,r),this.getGlobalState().onFlowStateChangeHandlers.push(r)},n.removeStateChangeHandler=l=>{let r=this.getGlobalState().onStepStateChangeHandlerWrappers.get(l);r&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(d=>d!==r))},e.set(i.id,n)}),this.steps=e,this.getGlobalState().variables&&this.getGlobalState().variables[this.id]&&Object.keys(this.getGlobalState().variables[this.id]).length>0&&this.applyVariables(this.getGlobalState().variables[this.id])}start(t){return h(this,null,function*(){if(this.isStarted||this.isCompleted)return;let e=u(this.getGlobalState().flowStates[this.id]);e.$state.started=!0,this.getGlobalState().flowStates[this.id]=e,this.resyncState(),yield this.sendFlowStateToAPI(M,t)})}complete(t){return h(this,null,function*(){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),yield this.sendFlowStateToAPI(D,t))})}skip(t){return h(this,null,function*(){this.isSkipped||(this.optimisticallyMarkFlowSkipped(),yield this.sendFlowStateToAPI(H,t))})}forward(t){return h(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e?yield e.start(t):yield this.complete(t)})}back(t){return h(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&(yield e.start(t))})}restart(){return h(this,null,function*(){this.optimisticallyMarkFlowNotStarted(),yield this.sendFlowStateToAPI(L)})}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){var t;return(t=this.steps.get(this.getStatefulFlow().$state.currentStepId))!=null?t:this.steps.get(Array.from(this.steps.keys())[0])}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.completed).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.visible).length}onStateChange(t){let e=(i,o)=>{i.id===this.id&&(i.isCompleted!==(o==null?void 0:o.isCompleted)||i.isStarted!==(o==null?void 0:o.isStarted)||i.isSkipped!==(o==null?void 0:o.isSkipped)||i.isVisible!==(o==null?void 0:o.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(o==null?void 0:o.steps))&&t(i,o)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,e),this.getGlobalState().onFlowStateChangeHandlers.push(e)}removeStateChangeHandler(t){let e=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);e&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(i=>i!==e))}applyVariables(t){var i,o;let e=n=>{let l=n.match(/\${(.*?)}/g);return l&&l.forEach(r=>{let d=r.replace("${","").replace("}","");t[d]&&(n=n.replace(r,t[d]))}),n};this.title=e((i=this.title)!=null?i:""),this.subtitle=e((o=this.subtitle)!=null?o:""),this.steps.forEach(n=>{Object.keys(n).forEach(l=>{typeof n[l]=="string"&&(n[l]=e(n[l]))})}),this.getGlobalState().variables={},this.getGlobalState().variables[this.id]=t}getStatefulFlow(){return this.getGlobalState().flowStates[this.id]}optimisticallyMarkFlowCompleted(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.completed=!0,t.$state.started=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}optimisticallyMarkFlowNotStarted(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.completed=!1,t.$state.started=!1,t.$state.visible=!0,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}sendFlowStateToAPI(t,e,i){return h(this,null,function*(){let o=new Date;this.getGlobalState().lastSyncDate=o;let n=yield this.fetch("/flowStates",{method:"POST",body:JSON.stringify({userId:this.config.userId,groupId:this.config.groupId,flowSlug:this.id,stepId:i!=null?i:this.getCurrentStep().id,data:e?JSON.stringify(e):{},actionType:t,createdAt:o})});o<this.getGlobalState().lastSyncDate||(yield this.getGlobalState().refreshStateFromAPI(n))})}optimisticallyMarkFlowSkipped(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.skipped=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}register(t){this.getGlobalState().rulesGraph.register(this.id,t)}unregister(){this.getGlobalState().rulesGraph.unregister(this.id)}};var k="NOT_STARTED_STEP",D="COMPLETED_FLOW",H="SKIPPED_FLOW",M="STARTED_FLOW",L="NOT_STARTED_FLOW",W="COMPLETED_STEP",U="STARTED_STEP",J="frigade-guest-key",E="guest_",et="get-cache-",O="fr-js-";function G(a){return new w({config:a.config,id:a.id})}function u(a){return JSON.parse(JSON.stringify(a))}function A(a){return{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json","X-Frigade-SDK-Version":_,"X-Frigade-SDK-Platform":"Javascript"}}}function it(a){return b()?window.localStorage.getItem(`${O}${a}`):null}function st(a,s){b()&&window.localStorage.setItem(`${O}${a}`,s)}function V(){Object.keys(g).forEach(a=>{a.startsWith(et)&&delete g[a]})}function j(){b()&&Object.keys(window.localStorage).forEach(a=>{a.startsWith(O)&&window.localStorage.removeItem(a)})}var T=class{constructor(){this.queue=[];this.ttlInMS=500;this.cacheSize=5}push(s){let t=new Date;this.queue.length>=this.cacheSize&&this.queue.shift(),this.queue.push({call:s,time:t.getTime()})}hasIdenticalCall(s){let t=new Date;return this.queue=this.queue.filter(e=>t.getTime()-e.time<this.ttlInMS),this.queue.some(e=>e.call===s)}},K=new T;function x(a,s){return h(this,null,function*(){var e;if(typeof globalThis.fetch!="function")return S("- Attempted to call fetch() in an environment that doesn't support it.");if(b()&&s&&s.body&&s.method==="POST"){let i=`${a}${JSON.stringify((e=s.body)!=null?e:{})}`;if(K.hasIdenticalCall(i))return S();K.push(i)}let t;try{t=fetch(a,s),t=yield t}catch(i){return S(i)}if(!t)return S("Received an empty response");if(t.status>=400)return S(t.statusText);try{if(t.status===204)return S();let i;try{i=yield t.json()}catch(o){return S()}return i.error?S(i.error):i}catch(i){return S(i)}})}function S(a){return a&&console.log("Call to Frigade failed",a),{json:()=>({})}}function N(){if(b()){let a=it(J);return a||(a=`${E}${tt()}`,st(J,a)),a}}function b(){return typeof window!="undefined"&&typeof window.document!="undefined"&&typeof window.localStorage!="undefined"}var C=class{constructor(s,t){this.graph=new Map;this.registry=new Map;this.ruleOrder=[];var e,i;this._rawGraphData=s,t&&(this.registry=t),this.ruleOrder=(e=s==null?void 0:s.ruleOrder)!=null?e:[],this.ingestGraphData((i=s==null?void 0:s.graph)!=null?i:{})}get rawGraphData(){return this._rawGraphData}ingestGraphData(s){this.graph=new Map(Object.entries(s)),this.fireCallbacks()}fireCallbacks(){for(let[s,t]of this.registry)typeof t=="function"&&t(this.isFlowVisible(s))}isFlowVisible(s){let t=this.graph.get(s);return t?t.visible===!1?!1:t.edges.length===0?!0:this.findRegisteredDescendant(s)==null:!0}register(s,t){this.registry.set(s,t),this.fireCallbacks()}unregister(s){this.registry.delete(s),this.fireCallbacks()}getRegistry(){return this.registry}findRegisteredDescendant(s,t=s,e){let i=this.graph.get(s);if(i==null)return;if(this.registry.has(s)&&t!==s)return i;let o;if(i.edges.length>0)for(let n of i.edges){if(e!=null&&n.ruleId!==e)continue;let l=this.findRegisteredDescendant(n.head,t,e!=null?e:n.ruleId);if(l!=null&&l.visible){o=l;break}}return o}};var R=class extends m{constructor(t,e){super(f({apiKey:t},e));this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=()=>h(this,null,function*(){document.visibilityState==="visible"&&(yield this.refreshStateFromAPI())});this.init(this.config),b()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(b()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=F(this.config);g[t]&&(g[t].onFlowStateChangeHandlers=[])}}init(t){return h(this,null,function*(){return this.config=f(f({},this.config),t),this.initPromise=(()=>h(this,null,function*(){var e;this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(E))&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})),yield this.refreshStateFromAPI()}))(),this.initPromise})}identify(t,e){return h(this,null,function*(){this.config=y(f({},this.config),{userId:t}),yield this.initIfNeeded(),yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),yield this.resync()})}group(t,e){return h(this,null,function*(){yield this.initIfNeeded(),this.config.groupId=t,yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:e})}),yield this.resync()})}track(t,e){return h(this,null,function*(){if(yield this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})})),yield this.resync()})}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}getFlow(t){return h(this,null,function*(){return yield this.initIfNeeded(),this.flows.find(e=>e.id==t)})}getFlows(){return h(this,null,function*(){return yield this.initIfNeeded(),this.flows})}reload(){return h(this,null,function*(){j(),V(),yield this.refreshStateFromAPI(),this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,G(t))})})})}resync(){return h(this,null,function*(){this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,G(t))})})})}onStateChange(t){return h(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers.push(t)})}hasFailedToLoad(){return this.hasFailed}removeStateChangeHandler(t){return h(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(e=>e!==t)})}initIfNeeded(){return h(this,null,function*(){return this.initPromise!==null?this.initPromise:this.init(this.config)})}refreshStateFromAPI(){return h(this,null,function*(){let t=F(this.config);if(!g[t]){let e=this,i={set:function(o,n,l){if(o[n]){let r=o[n],d=l;JSON.stringify(r)!==JSON.stringify(d)&&e.triggerEventHandlers(d,r)}return o[n]=l,!0}};if(g[t]={refreshStateFromAPI:()=>h(this,null,function*(){}),rulesGraph:new C({graph:{},ruleOrder:[]}),flowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map,variables:{}},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockFlowStates(t);return}g[t].refreshStateFromAPI=o=>h(this,null,function*(){var r,d,p;if(this.config.__readOnly)return;let n=o||(yield this.fetch(`/flowStates?userId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&groupId=${encodeURIComponent(this.config.groupId)}`:""}`)),l=JSON.stringify(g[t].rulesGraph.rawGraphData)!==JSON.stringify((r=n.ruleGraph)==null?void 0:r.graph);g[t].rulesGraph=new C(n.ruleGraph,(p=(d=g[t])==null?void 0:d.rulesGraph)==null?void 0:p.getRegistry()),l&&this.flows.forEach(c=>{var v;if((v=n.ruleGraph)!=null&&v.graph[c.id]){let q=n.eligibleFlows.find(I=>I.flowSlug===c.id),B=this.getGlobalState().previousFlows.get(c.id);c.resyncState(q),this.getGlobalState().onFlowStateChangeHandlers.forEach(I=>{I(c,B),this.getGlobalState().previousFlows.set(c.id,G(c))})}}),n&&n.eligibleFlows?(n.eligibleFlows.forEach(c=>{g[t].flowStates[c.flowSlug]=c,this.flows.find(v=>v.id==c.flowSlug)||this.flows.push(new w({config:this.config,id:c.flowSlug}))}),this.hasFailed=!1):this.hasFailed=!0})}yield g[t].refreshStateFromAPI()})}mockFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var o,n,l;let i=JSON.parse(this.config.__flowConfigOverrides[e]);g[t].flowStates[e]={flowSlug:e,flowName:(o=i==null?void 0:i.name)!=null?o:e,flowType:(n=i==null?void 0:i.type)!=null?n:"CHECKLIST",data:y(f({},i),{steps:((l=i==null?void 0:i.steps)!=null?l:[]).map(r=>f({id:r.id,$state:{completed:!1,started:!1,visible:!0,blocked:!1}},r))}),$state:{currentStepId:null,currentStepIndex:-1,completed:!1,started:!1,skipped:!1,visible:!0}},this.flows.push(new w({config:this.config,id:e}))})}triggerEventHandlers(t,e){return h(this,null,function*(){t&&this.flows.forEach(i=>{i.id==e.flowSlug&&this.getGlobalState().onFlowStateChangeHandlers.forEach(o=>{let n=this.getGlobalState().previousFlows.get(i.id);i.resyncState(t),o(i,n),this.getGlobalState().previousFlows.set(i.id,G(i))})})})}};export{w as Flow,R as Frigade};
|
|
2
|
+
var J=Object.defineProperty,j=Object.defineProperties;var q=Object.getOwnPropertyDescriptors;var O=Object.getOwnPropertySymbols;var B=Object.prototype.hasOwnProperty,X=Object.prototype.propertyIsEnumerable;var R=(r,s,t)=>s in r?J(r,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[s]=t,p=(r,s)=>{for(var t in s||(s={}))B.call(s,t)&&R(r,t,s[t]);if(O)for(var t of O(s))X.call(s,t)&&R(r,t,s[t]);return r},y=(r,s)=>j(r,q(s));var c=(r,s,t)=>new Promise((e,i)=>{var a=o=>{try{l(t.next(o))}catch(d){i(d)}},n=o=>{try{l(t.throw(o))}catch(d){i(d)}},l=o=>o.done?e(o.value):Promise.resolve(o.value).then(a,n);l((t=t.apply(r,s)).next())});var $="0.2.20";import{v4 as z}from"uuid";var f={};function G(r){var s,t;return`${r.__instanceId}-${r.apiKey}:${(s=r.userId)!=null?s:""}:${(t=r.groupId)!=null?t:""}`}var m=class{constructor(s){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:_(),__instanceId:Math.random().toString(12).substring(4)};let t=Object.fromEntries(Object.entries(s).filter(([e,i])=>i!=null));this.config=p(p({},this.config),t)}fetch(s,t){return c(this,null,function*(){return this.config.__readOnly?S():A(this.getAPIUrl(s),p(p({keepalive:!0},t!=null?t:{}),P(this.config.apiKey)))})}getAPIUrl(s){let t="/v1/public";return new URL(`${t}${s}`,this.config.apiUrl.replace(t,"")).toString()}getGlobalState(){let s=G(this.config);if(!f[s])throw new Error("Frigade has not yet been initialized");return f[s]}};var w=class extends m{constructor({config:t,id:e}){super(t);this._isVisible=!1;this.lastStepUpdate=new Map;this.id=e,this.init()}get isVisible(){return this._isVisible===!1?!1:this.getGlobalState().rulesGraph.isFlowVisible(this.id)}set isVisible(t){this._isVisible=t}reload(){this.init()}resyncState(t){var i,a;let e=t!=null?t:this.getStatefulFlow();this.rawData=e,this.title=(i=e==null?void 0:e.data)==null?void 0:i.title,this.subtitle=(a=e==null?void 0:e.data)==null?void 0:a.subtitle,this.isCompleted=e.$state.completed,this.isStarted=e.$state.started,this.isSkipped=e.$state.skipped,this._isVisible=e.$state.visible,e.data.steps.forEach((n,l)=>{var g;let o=this.initStepFromStatefulStep(n,l),d=(g=this.steps)==null?void 0:g.get(n.id);d&&(d.$state=o.$state)})}initStepFromStatefulStep(t,e){return y(p({},t),{flow:this,$state:y(p({},t.$state),{lastActionAt:t.$state.lastActionAt?new Date(t.$state.lastActionAt):void 0}),order:e})}init(){let t=this.getStatefulFlow();this.resyncState();let e=new Map;t.data.steps.forEach((i,a)=>{let n=this.initStepFromStatefulStep(i,a);n.start=l=>c(this,null,function*(){let o=this.steps.get(i.id);if(this.getCurrentStep().id===o.id&&o.$state.started)return;let d=u(this.getGlobalState().flowStates[this.id]);d.data.steps[o.order].$state.started=!0,d.data.steps[o.order].$state.lastActionAt=new Date,d.$state.lastActionAt=new Date,d.$state.currentStepId=o.id,d.$state.currentStepIndex=o.order,this.getGlobalState().flowStates[this.id]=d,this.resyncState(),o.$state.completed||(yield this.sendFlowStateToAPI(L,l,o.id))}),n.complete=l=>c(this,null,function*(){let o=this.steps.get(i.id);if(o.$state.completed)return;let g=this.getNumberOfCompletedSteps()+1==this.steps.size,h=u(this.getGlobalState().flowStates[this.id]);h.$state.started=!0,h.data.steps[o.order].$state.completed=!0,h.data.steps[o.order].$state.started=!0,h.data.steps[o.order].$state.lastActionAt=new Date,g||(h.$state.currentStepId=this.getStepByIndex(o.order+1).id,h.$state.currentStepIndex=o.order+1),g&&(h.$state.completed=!0),this.getGlobalState().flowStates[this.id]=h,this.resyncState(),g&&this.optimisticallyMarkFlowCompleted(),yield this.sendFlowStateToAPI(M,l,o.id)}),n.reset=()=>c(this,null,function*(){let l=this.steps.get(i.id);if(!l.$state.completed)return;let o=u(this.getGlobalState().flowStates[this.id]);o.data.steps[l.order].$state.started=!1,o.data.steps[l.order].$state.completed=!1,o.data.steps[l.order].$state.lastActionAt=void 0,this.getGlobalState().flowStates[this.id]=o,this.resyncState(),yield this.sendFlowStateToAPI(x,void 0,l.id)}),n.onStateChange=l=>{let o=d=>{if(d.id!==this.id)return;let g=d.steps.get(i.id),h=this.lastStepUpdate.get(l);(g.$state.completed!==(h==null?void 0:h.$state.completed)||g.$state.started!==(h==null?void 0:h.$state.started)||g.$state.visible!==(h==null?void 0:h.$state.visible)||g.$state.blocked!==(h==null?void 0:h.$state.blocked))&&(l(g,h!=null?h:u(g)),this.lastStepUpdate.set(l,u(g)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(l,o),this.getGlobalState().onFlowStateChangeHandlers.push(o)},n.removeStateChangeHandler=l=>{let o=this.getGlobalState().onStepStateChangeHandlerWrappers.get(l);o&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(d=>d!==o))},e.set(i.id,n)}),this.steps=e,this.getGlobalState().variables&&this.getGlobalState().variables[this.id]&&Object.keys(this.getGlobalState().variables[this.id]).length>0&&this.applyVariables(this.getGlobalState().variables[this.id])}start(t){return c(this,null,function*(){if(this.isStarted||this.isCompleted)return;let e=u(this.getGlobalState().flowStates[this.id]);e.$state.started=!0,this.getGlobalState().flowStates[this.id]=e,this.resyncState(),yield this.sendFlowStateToAPI(H,t)})}complete(t){return c(this,null,function*(){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),yield this.sendFlowStateToAPI(N,t))})}skip(t){return c(this,null,function*(){this.isSkipped||(this.optimisticallyMarkFlowSkipped(),yield this.sendFlowStateToAPI(D,t))})}forward(t){return c(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e?yield e.start(t):yield this.complete(t)})}back(t){return c(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&(yield e.start(t))})}restart(){return c(this,null,function*(){this.optimisticallyMarkFlowNotStarted(),yield this.sendFlowStateToAPI(k)})}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){var t;return(t=this.steps.get(this.getStatefulFlow().$state.currentStepId))!=null?t:this.steps.get(Array.from(this.steps.keys())[0])}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.completed).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.visible).length}onStateChange(t){let e=(i,a)=>{i.id===this.id&&(i.isCompleted!==(a==null?void 0:a.isCompleted)||i.isStarted!==(a==null?void 0:a.isStarted)||i.isSkipped!==(a==null?void 0:a.isSkipped)||i.isVisible!==(a==null?void 0:a.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(a==null?void 0:a.steps))&&t(i,a)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,e),this.getGlobalState().onFlowStateChangeHandlers.push(e)}removeStateChangeHandler(t){let e=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);e&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(i=>i!==e))}applyVariables(t){var i,a;let e=n=>{let l=n.match(/\${(.*?)}/g);return l&&l.forEach(o=>{let d=o.replace("${","").replace("}","");t[d]&&(n=n.replace(o,t[d]))}),n};this.title=e((i=this.title)!=null?i:""),this.subtitle=e((a=this.subtitle)!=null?a:""),this.steps.forEach(n=>{Object.keys(n).forEach(l=>{typeof n[l]=="string"&&(n[l]=e(n[l]))})}),this.getGlobalState().variables={},this.getGlobalState().variables[this.id]=t}getStatefulFlow(){return this.getGlobalState().flowStates[this.id]}optimisticallyMarkFlowCompleted(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.completed=!0,t.$state.started=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}optimisticallyMarkFlowNotStarted(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.completed=!1,t.$state.started=!1,t.$state.visible=!0,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}sendFlowStateToAPI(t,e,i){return c(this,null,function*(){let a=new Date;this.getGlobalState().lastSyncDate=a;let n=yield this.fetch("/flowStates",{method:"POST",body:JSON.stringify({userId:this.config.userId,groupId:this.config.groupId,flowSlug:this.id,stepId:i!=null?i:this.getCurrentStep().id,data:e?JSON.stringify(e):{},actionType:t,createdAt:a})});a<this.getGlobalState().lastSyncDate||(yield this.getGlobalState().refreshStateFromAPI(n))})}optimisticallyMarkFlowSkipped(){let t=u(this.getGlobalState().flowStates[this.id]);t.$state.skipped=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}register(t){this.getGlobalState().rulesGraph.register(this.id,i=>{let a=this.getGlobalState().previousFlows.get(this.id);(a==null?void 0:a._isVisible)!==i&&this.getGlobalState().onFlowStateChangeHandlers.forEach(n=>{n(this,a),this.getGlobalState().previousFlows.set(this.id,F(this))}),t==null||t(i)})}unregister(){this.getGlobalState().rulesGraph.unregister(this.id)}};var x="NOT_STARTED_STEP",N="COMPLETED_FLOW",D="SKIPPED_FLOW",H="STARTED_FLOW",k="NOT_STARTED_FLOW",M="COMPLETED_STEP",L="STARTED_STEP",W="frigade-guest-key",I="guest_",Y="get-cache-",T="fr-js-";function F(r){return new w({config:r.config,id:r.id})}function u(r){return JSON.parse(JSON.stringify(r))}function P(r){return{headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json","X-Frigade-SDK-Version":$,"X-Frigade-SDK-Platform":"Javascript"}}}function Q(r){return b()?window.localStorage.getItem(`${T}${r}`):null}function Z(r,s){b()&&window.localStorage.setItem(`${T}${r}`,s)}function K(){Object.keys(f).forEach(r=>{r.startsWith(Y)&&delete f[r]})}function V(){b()&&Object.keys(window.localStorage).forEach(r=>{r.startsWith(T)&&window.localStorage.removeItem(r)})}var v=class{constructor(){this.queue=[];this.ttlInMS=500;this.cacheSize=5}push(s){let t=new Date;this.queue.length>=this.cacheSize&&this.queue.shift(),this.queue.push({call:s,time:t.getTime()})}hasIdenticalCall(s){let t=new Date;return this.queue=this.queue.filter(e=>t.getTime()-e.time<this.ttlInMS),this.queue.some(e=>e.call===s)}},U=new v;function A(r,s){return c(this,null,function*(){var e;if(typeof globalThis.fetch!="function")return S("- Attempted to call fetch() in an environment that doesn't support it.");if(b()&&s&&s.body&&s.method==="POST"){let i=`${r}${JSON.stringify((e=s.body)!=null?e:{})}`;if(U.hasIdenticalCall(i))return S();U.push(i)}let t;try{t=fetch(r,s),t=yield t}catch(i){return S(i)}if(!t)return S("Received an empty response");if(t.status>=400)return S(t.statusText);try{if(t.status===204)return S();let i;try{i=yield t.json()}catch(a){return S()}return i.error?S(i.error):i}catch(i){return S(i)}})}function S(r){return r&&console.log("Call to Frigade failed",r),{json:()=>({})}}function _(){if(b()){let r=Q(W);return r||(r=`${I}${z()}`,Z(W,r)),r}}function b(){return typeof window!="undefined"&&typeof window.document!="undefined"&&typeof window.localStorage!="undefined"}var C=class{constructor(s){this.graph=new Map;this.registry=new Map;this.ruleOrder=[];var t,e;this.ruleOrder=(t=s==null?void 0:s.ruleOrder)!=null?t:[],this.ingestGraphData((e=s==null?void 0:s.graph)!=null?e:{})}ingestGraphData(s){this.graph=new Map(Object.entries(s)),this.fireCallbacks()}fireCallbacks(){for(let[s,t]of this.registry)typeof t=="function"&&t(this.isFlowVisible(s))}isFlowVisible(s){let t=this.graph.get(s);return t?t.visible===!1?!1:t.edges.length===0?!0:this.findRegisteredDescendant(s)==null:!0}register(s,t){this.registry.set(s,t!=null?t:()=>{}),this.fireCallbacks()}unregister(s){this.registry.delete(s),this.fireCallbacks()}getRegistry(){return this.registry}findRegisteredDescendant(s,t=s,e){let i=this.graph.get(s);if(i==null)return;if(this.registry.has(s)&&t!==s)return i;let a;if(i.edges.length>0)for(let n of i.edges){if(e!=null&&n.ruleId!==e)continue;let l=this.findRegisteredDescendant(n.head,t,e!=null?e:n.ruleId);if(l!=null&&l.visible){a=l;break}}return a}};var E=class extends m{constructor(t,e){super(p({apiKey:t},e));this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=()=>c(this,null,function*(){document.visibilityState==="visible"&&(yield this.refreshStateFromAPI())});this.init(this.config),b()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(b()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=G(this.config);f[t]&&(f[t].onFlowStateChangeHandlers=[])}}init(t){return c(this,null,function*(){return this.config=p(p({},this.config),t),this.initPromise=(()=>c(this,null,function*(){var e;this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(I))&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})),yield this.refreshStateFromAPI()}))(),this.initPromise})}identify(t,e){return c(this,null,function*(){this.config=y(p({},this.config),{userId:t}),yield this.initIfNeeded(),yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),yield this.resync()})}group(t,e){return c(this,null,function*(){yield this.initIfNeeded(),this.config.groupId=t,yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:e})}),yield this.resync()})}track(t,e){return c(this,null,function*(){if(yield this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})})),yield this.resync()})}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}getFlow(t){return c(this,null,function*(){return yield this.initIfNeeded(),this.flows.find(e=>e.id==t)})}getFlows(){return c(this,null,function*(){return yield this.initIfNeeded(),this.flows})}reload(){return c(this,null,function*(){V(),K(),yield this.refreshStateFromAPI(),this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,F(t))})})})}resync(){return c(this,null,function*(){this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,F(t))})})})}onStateChange(t){return c(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers.push(t)})}hasFailedToLoad(){return this.hasFailed}removeStateChangeHandler(t){return c(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(e=>e!==t)})}initIfNeeded(){return c(this,null,function*(){return this.initPromise!==null?this.initPromise:this.init(this.config)})}refreshStateFromAPI(){return c(this,null,function*(){let t=G(this.config);if(!f[t]){let e=this,i={set:function(a,n,l){if(a[n]){let o=a[n],d=l;JSON.stringify(o)!==JSON.stringify(d)&&e.triggerEventHandlers(d,o)}return a[n]=l,!0}};if(f[t]={refreshStateFromAPI:()=>c(this,null,function*(){}),rulesGraph:new C({graph:{},ruleOrder:[]}),flowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map,variables:{}},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockFlowStates(t);return}f[t].refreshStateFromAPI=a=>c(this,null,function*(){var l,o;if(this.config.__readOnly)return;let n=a||(yield this.fetch(`/flowStates?userId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&groupId=${encodeURIComponent(this.config.groupId)}`:""}`));f[t].rulesGraph.ingestGraphData((o=(l=n.ruleGraph)==null?void 0:l.graph)!=null?o:{}),n&&n.eligibleFlows?(n.eligibleFlows.forEach(d=>{f[t].flowStates[d.flowSlug]=d,this.flows.find(g=>g.id==d.flowSlug)||this.flows.push(new w({config:this.config,id:d.flowSlug}))}),this.hasFailed=!1):this.hasFailed=!0})}yield f[t].refreshStateFromAPI()})}mockFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var a,n,l;let i=JSON.parse(this.config.__flowConfigOverrides[e]);f[t].flowStates[e]={flowSlug:e,flowName:(a=i==null?void 0:i.name)!=null?a:e,flowType:(n=i==null?void 0:i.type)!=null?n:"CHECKLIST",data:y(p({},i),{steps:((l=i==null?void 0:i.steps)!=null?l:[]).map(o=>p({id:o.id,$state:{completed:!1,started:!1,visible:!0,blocked:!1}},o))}),$state:{currentStepId:null,currentStepIndex:-1,completed:!1,started:!1,skipped:!1,visible:!0}},this.flows.push(new w({config:this.config,id:e}))})}triggerEventHandlers(t,e){return c(this,null,function*(){t&&this.flows.forEach(i=>{i.id==e.flowSlug&&this.getGlobalState().onFlowStateChangeHandlers.forEach(a=>{let n=this.getGlobalState().previousFlows.get(i.id);i.resyncState(t),a(i,n),this.getGlobalState().previousFlows.set(i.id,F(i))})})})}};export{w as Flow,E 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/rules-graph.ts","../src/core/frigade.ts"],"sourcesContent":["export const VERSION_NUMBER = '0.2.20'\n","import { VERSION_NUMBER } from '../core/version'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { frigadeGlobalState } from './state'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nconst GUEST_KEY = 'frigade-guest-key'\nexport const GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow({\n config: flow.config,\n id: flow.id,\n })\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n }\n}\n\nfunction setGlobalState(key: string, value: any) {\n frigadeGlobalState[key] = value\n}\n\nfunction getGlobalState(key: string): any {\n return frigadeGlobalState[key]\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nclass CallQueue {\n private queue: {\n call: string\n time: number\n }[] = []\n private readonly ttlInMS = 500\n private readonly cacheSize = 5\n\n public push(call: string) {\n const now = new Date()\n if (this.queue.length >= this.cacheSize) {\n this.queue.shift()\n }\n this.queue.push({\n call: call,\n time: now.getTime(),\n })\n }\n\n public hasIdenticalCall(call: string) {\n const now = new Date()\n this.queue = this.queue.filter((item) => now.getTime() - item.time < this.ttlInMS)\n return this.queue.some((item) => item.call === call)\n }\n}\n\nconst callQueue = new CallQueue()\n\nexport async function gracefulFetch(url: string, options: any) {\n if (typeof globalThis.fetch !== 'function') {\n return getEmptyResponse(\n \"- Attempted to call fetch() in an environment that doesn't support it.\"\n )\n }\n\n if (isWeb() && options && options.body && options.method === 'POST') {\n const lastCallDataKey = `${url}${JSON.stringify(options.body ?? {})}`\n if (callQueue.hasIdenticalCall(lastCallDataKey)) {\n return getEmptyResponse()\n }\n callQueue.push(lastCallDataKey)\n }\n\n let response\n try {\n response = fetch(url, options)\n response = await response\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n if (response.status === 204) {\n return getEmptyResponse()\n }\n\n let body\n try {\n body = await response.json()\n } catch (e) {\n return getEmptyResponse()\n }\n\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nexport function getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n\nexport function isWeb() {\n return (\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.localStorage !== 'undefined'\n )\n}\n","import { FlowStates, FlowStep, FrigadeConfig, StatefulFlow } from '../core/types'\nimport { Flow } from '../core/flow'\nimport { RulesGraph } from '../core/rules-graph'\n\nexport interface FrigadeGlobalState {\n refreshStateFromAPI: (overrideFlowStatesRaw?: FlowStates) => Promise<void>\n flowStates: Record<string, StatefulFlow>\n rulesGraph: RulesGraph\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 variables: Record<string, Record<string, any>>\n lastSyncDate?: Date\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.groupId ?? ''\n }`\n}\n","import { generateGuestId, getEmptyResponse, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../core/types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(12).substring(4),\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(this.getAPIUrl(path), {\n keepalive: true,\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n private getAPIUrl(path: string) {\n const pathPrefix = '/v1/public'\n const apiUrl = new URL(\n `${pathPrefix}${path}`,\n this.config.apiUrl.replace(pathPrefix, '')\n ).toString()\n\n return apiUrl\n }\n\n /**\n * @ignore\n */\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade has not yet been initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import {\n FlowActionType,\n FlowStateDTO,\n FlowStates,\n FlowStep,\n FrigadeConfig,\n StatefulFlow,\n StatefulStep,\n} from './types'\nimport {\n clone,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n NOT_STARTED_STEP,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { Fetchable } from '../shared/fetchable'\nimport { RulesGraphRegistryCallback } from './rules-graph'\n\nexport class Flow extends Fetchable {\n /**\n * The Flow's ID.\n */\n public id: string\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The metadata of the Flow.\n * @ignore\n */\n public rawData: StatefulFlow\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 * @ignore\n */\n private _isVisible: boolean = false\n /**\n * Whether the Flow is visible to the user based on the current user/group's state.\n */\n get isVisible() {\n if (this._isVisible === false) {\n return false\n }\n\n return this.getGlobalState().rulesGraph.isFlowVisible(this.id)\n }\n set isVisible(visible: boolean) {\n this._isVisible = visible\n }\n\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n constructor({ config, id }: { config: FrigadeConfig; id: string }) {\n super(config)\n this.id = id\n this.init()\n }\n\n /**\n * Reload the Flow data from the server\n */\n reload() {\n this.init()\n }\n\n /**\n * @ignore\n */\n resyncState(overrideStatefulFlow?: StatefulFlow) {\n const statefulFlow = overrideStatefulFlow ?? this.getStatefulFlow()\n\n this.rawData = statefulFlow\n this.title = statefulFlow?.data?.title\n this.subtitle = statefulFlow?.data?.subtitle\n\n this.isCompleted = statefulFlow.$state.completed\n this.isStarted = statefulFlow.$state.started\n this.isSkipped = statefulFlow.$state.skipped\n this._isVisible = statefulFlow.$state.visible\n\n // Set\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n const existingStep = this.steps?.get(step.id)\n if (existingStep) {\n existingStep.$state = stepObj.$state\n }\n })\n }\n\n /**\n * @ignore\n */\n private initStepFromStatefulStep(step: StatefulStep, index: number) {\n return {\n ...step,\n flow: this,\n $state: {\n ...step.$state,\n lastActionAt: step.$state.lastActionAt ? new Date(step.$state.lastActionAt) : undefined,\n },\n order: index,\n } as Partial<FlowStep>\n }\n\n /**\n * @ignore\n */\n private init() {\n const statefulFlow = this.getStatefulFlow()\n\n this.resyncState()\n\n const newSteps = new Map<string, FlowStep>()\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.$state.started) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n copy.$state.lastActionAt = new Date()\n copy.$state.currentStepId = thisStep.id\n copy.$state.currentStepIndex = thisStep.order\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (!thisStep.$state.completed) {\n await this.sendFlowStateToAPI(STARTED_STEP, properties, thisStep.id)\n }\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (thisStep.$state.completed) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n const copy = clone(this.getGlobalState().flowStates[this.id])\n\n copy.$state.started = true\n copy.data.steps[thisStep.order].$state.completed = true\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n\n // If there are more index, advance current step\n if (!isLastStep) {\n copy.$state.currentStepId = this.getStepByIndex(thisStep.order + 1).id\n copy.$state.currentStepIndex = thisStep.order + 1\n }\n\n if (isLastStep) {\n copy.$state.completed = true\n }\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n await this.sendFlowStateToAPI(COMPLETED_STEP, properties, thisStep.id)\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.$state.completed) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = false\n copy.data.steps[thisStep.order].$state.completed = false\n copy.data.steps[thisStep.order].$state.lastActionAt = undefined\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(NOT_STARTED_STEP, undefined, thisStep.id)\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.$state.completed !== previousStep?.$state.completed ||\n thisStep.$state.started !== previousStep?.$state.started ||\n thisStep.$state.visible !== previousStep?.$state.visible ||\n thisStep.$state.blocked !== previousStep?.$state.blocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj as FlowStep)\n })\n this.steps = newSteps\n // Check if empty object\n if (\n this.getGlobalState().variables &&\n this.getGlobalState().variables[this.id] &&\n Object.keys(this.getGlobalState().variables[this.id]).length > 0\n ) {\n this.applyVariables(this.getGlobalState().variables[this.id])\n }\n }\n\n /**\n * Marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.started = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(STARTED_FLOW, properties)\n }\n\n /**\n * Marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n await this.sendFlowStateToAPI(COMPLETED_FLOW, properties)\n }\n\n /**\n * Marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n if (this.isSkipped) {\n return\n }\n this.optimisticallyMarkFlowSkipped()\n await this.sendFlowStateToAPI(SKIPPED_FLOW, properties)\n }\n\n /**\n * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: Record<string | number, any>) {\n const nextStep = this.getStepByIndex(this.getCurrentStepIndex() + 1)\n if (nextStep) {\n await nextStep.start(properties)\n } else {\n await this.complete(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: Record<string | number, any>) {\n const previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n this.optimisticallyMarkFlowNotStarted()\n await this.sendFlowStateToAPI(NOT_STARTED_FLOW)\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Gets current step\n */\n public getCurrentStep(): FlowStep {\n return (\n this.steps.get(this.getStatefulFlow().$state.currentStepId) ??\n this.steps.get(Array.from(this.steps.keys())[0])\n )\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.completed).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.visible).length\n }\n\n /**\n * @ignore\n */\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (flow.id === this.id) {\n if (\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 }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n /**\n * @ignore\n */\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n /**\n * @ignore\n */\n public applyVariables(variables: Record<string, any>) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n if (!variables[variable]) {\n return\n }\n str = str.replace(match, variables[variable])\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n this.steps.forEach((step) => {\n // Iterate over every string field in the step and replace variables\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n }\n })\n })\n\n this.getGlobalState().variables = {}\n this.getGlobalState().variables[this.id] = variables\n }\n\n /**\n * @ignore\n */\n private getStatefulFlow(): StatefulFlow {\n const userFlowStates = this.getGlobalState().flowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowCompleted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = true\n copy.$state.started = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowNotStarted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = false\n copy.$state.started = false\n copy.$state.visible = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n private async sendFlowStateToAPI(\n action: FlowActionType,\n data?: Record<string | number, any>,\n stepId?: string\n ) {\n const date = new Date()\n this.getGlobalState().lastSyncDate = date\n const flowStatesRaw: FlowStates = await this.fetch('/flowStates', {\n method: 'POST',\n body: JSON.stringify({\n userId: this.config.userId,\n groupId: this.config.groupId,\n flowSlug: this.id,\n stepId: stepId ?? this.getCurrentStep().id,\n data: data ? JSON.stringify(data) : {},\n actionType: action,\n createdAt: date,\n } as FlowStateDTO),\n })\n if (date < this.getGlobalState().lastSyncDate) {\n return\n }\n await this.getGlobalState().refreshStateFromAPI(flowStatesRaw)\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowSkipped() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.skipped = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n public register(callback?: RulesGraphRegistryCallback) {\n this.getGlobalState().rulesGraph.register(this.id, callback)\n }\n\n public unregister() {\n this.getGlobalState().rulesGraph.unregister(this.id)\n }\n}\n","import { RuleGraph } from './types'\n\nexport interface RulesGraphNode {\n visible: boolean\n edges: RulesGraphEdge[]\n}\n\nexport interface RulesGraphEdge {\n head: string\n ruleId: string\n}\n\nexport type RulesGraphRegistryCallback = (visible: boolean) => void\n\n// TODO: JSDoc this class\nexport class RulesGraph {\n private graph: Map<string, RulesGraphNode> = new Map()\n private readonly registry: Map<string, RulesGraphRegistryCallback> = new Map()\n private readonly _rawGraphData: RuleGraph\n private readonly ruleOrder: string[] = []\n public get rawGraphData() {\n return this._rawGraphData\n }\n\n constructor(graphData: RuleGraph, registry?: Map<string, RulesGraphRegistryCallback>) {\n this._rawGraphData = graphData\n if (registry) {\n this.registry = registry\n }\n this.ruleOrder = graphData?.ruleOrder ?? []\n this.ingestGraphData(graphData?.graph ?? {})\n }\n\n ingestGraphData(graphData: Record<string, RulesGraphNode>) {\n this.graph = new Map(Object.entries(graphData))\n\n this.fireCallbacks()\n }\n\n fireCallbacks() {\n for (const [flowId, callback] of this.registry) {\n if (typeof callback === 'function') {\n callback(this.isFlowVisible(flowId))\n }\n }\n }\n\n isFlowVisible(flowId: string) {\n const currentNode = this.graph.get(flowId)\n\n // Is the flow in the graph?\n // If not, it belongs to 0 rules and can carry on about its business\n if (!currentNode) {\n return true\n }\n\n if (currentNode.visible === false) {\n return false\n }\n\n // Does the flow have edges?\n // If not, it's the king of all flows, and it does what it wants\n if (currentNode.edges.length === 0) {\n return true\n }\n\n // Are any of the flow's descendants visible and in the registry already?\n const registeredDescendant = this.findRegisteredDescendant(flowId)\n\n // If so, this flow is not visible\n if (registeredDescendant != null) {\n return false\n }\n\n // Congrats! There are no conditions in the graph that disqualify this flow from being visible\n return true\n }\n\n register(flowId: string, callback?: RulesGraphRegistryCallback) {\n this.registry.set(flowId, callback)\n\n this.fireCallbacks()\n }\n\n unregister(flowId: string) {\n this.registry.delete(flowId)\n\n this.fireCallbacks()\n }\n\n getRegistry() {\n return this.registry\n }\n\n private findRegisteredDescendant(nodeId: string, originId = nodeId, ruleId?: string) {\n const node = this.graph.get(nodeId)\n\n if (node == null) {\n return undefined\n }\n\n if (this.registry.has(nodeId) && originId !== nodeId) {\n return node\n }\n\n let result = undefined\n\n if (node.edges.length > 0) {\n for (const edge of node.edges) {\n // If we went past the end of the rule, stop searching for this rule\n if (ruleId != null && edge.ruleId !== ruleId) {\n continue\n }\n\n const ancestor = this.findRegisteredDescendant(edge.head, originId, ruleId ?? edge.ruleId)\n\n if (ancestor != null && ancestor.visible) {\n result = ancestor\n break\n }\n }\n }\n\n return result\n }\n}\n","import { FlowStates, FrigadeConfig, StatefulFlow, StatefulStep } from './types'\nimport { clearCache, cloneFlow, GUEST_PREFIX, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/fetchable'\nimport { RulesGraph } from './rules-graph'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshStateFromAPI()\n }\n }\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n }\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\n */\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n if (this.config.userId && !this.config.userId?.startsWith(GUEST_PREFIX)) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n }),\n })\n }\n await this.refreshStateFromAPI()\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { ...this.config, userId }\n await this.initIfNeeded()\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.resync()\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = groupId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n properties,\n }),\n })\n await this.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n } else if (this.config.userId) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\n */\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n /**\n * Reload the current state of the flows by calling the Frigade API.\n * This will trigger all event handlers.\n */\n public async reload() {\n resetAllLocalStorage()\n clearCache()\n await this.refreshStateFromAPI()\n this.initPromise = null\n await this.init(this.config)\n // Trigger all event handlers\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n private async resync() {\n this.initPromise = null\n await this.init(this.config)\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @param handler\n */\n public async onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\n */\n public async removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n /**\n * @ignore\n */\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n /**\n * @ignore\n */\n private async refreshStateFromAPI(): 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 (target[key]) {\n const previousState = target[key] as StatefulFlow\n const newState = value as StatefulFlow\n if (JSON.stringify(previousState) !== JSON.stringify(newState)) {\n that.triggerEventHandlers(newState, previousState)\n }\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshStateFromAPI: async () => {},\n rulesGraph: new RulesGraph({\n graph: {},\n ruleOrder: [],\n }),\n flowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n variables: {},\n }\n\n if (this.config.__readOnly && this.config.__flowConfigOverrides) {\n this.mockFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshStateFromAPI = async (\n overrideFlowStateRaw?: FlowStates\n ) => {\n if (this.config.__readOnly) {\n return\n }\n\n const flowStateRaw: FlowStates = overrideFlowStateRaw\n ? overrideFlowStateRaw\n : await this.fetch(\n `/flowStates?userId=${encodeURIComponent(this.config.userId)}${\n this.config.groupId ? `&groupId=${encodeURIComponent(this.config.groupId)}` : ''\n }`\n )\n\n const hasRuleGraphChanged =\n JSON.stringify(frigadeGlobalState[globalStateKey].rulesGraph.rawGraphData) !==\n JSON.stringify(flowStateRaw.ruleGraph?.graph)\n\n frigadeGlobalState[globalStateKey].rulesGraph = new RulesGraph(\n flowStateRaw.ruleGraph,\n frigadeGlobalState[globalStateKey]?.rulesGraph?.getRegistry()\n )\n\n // Call all event handlers for the flows in the rulesgraph\n if (hasRuleGraphChanged) {\n this.flows.forEach((flow) => {\n if (flowStateRaw.ruleGraph?.graph[flow.id]) {\n const flowState = flowStateRaw.eligibleFlows.find((f) => f.flowSlug === flow.id)\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(flowState)\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n\n if (flowStateRaw && flowStateRaw.eligibleFlows) {\n flowStateRaw.eligibleFlows.forEach((statefulFlow) => {\n frigadeGlobalState[globalStateKey].flowStates[statefulFlow.flowSlug] = statefulFlow\n if (!this.flows.find((flow) => flow.id == statefulFlow.flowSlug)) {\n this.flows.push(\n new Flow({\n config: this.config,\n id: statefulFlow.flowSlug,\n })\n )\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshStateFromAPI()\n }\n\n /**\n * @ignore\n */\n private mockFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n const parsed = JSON.parse(this.config.__flowConfigOverrides[flowId])\n frigadeGlobalState[globalStateKey].flowStates[flowId] = {\n flowSlug: flowId,\n flowName: parsed?.name ?? flowId,\n flowType: parsed?.type ?? 'CHECKLIST',\n data: {\n ...parsed,\n steps: (parsed?.steps ?? []).map((step: any): StatefulStep => {\n return {\n id: step.id,\n $state: {\n completed: false,\n started: false,\n visible: true,\n blocked: false,\n },\n ...step,\n }\n }),\n },\n $state: {\n currentStepId: null,\n currentStepIndex: -1,\n completed: false,\n started: false,\n skipped: false,\n visible: true,\n },\n } as StatefulFlow\n\n this.flows.push(\n new Flow({\n config: this.config,\n id: flowId,\n })\n )\n })\n }\n\n /**\n * @ignore\n */\n private async triggerEventHandlers(newState: StatefulFlow, previousState?: StatefulFlow) {\n if (newState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousState.flowSlug) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(newState)\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","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","_a","_b","Fetchable","config","generateGuestId","filteredConfig","_","v","__spreadValues","path","options","__async","getEmptyResponse","gracefulFetch","getHeaders","pathPrefix","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","id","visible","overrideStatefulFlow","_a","_b","statefulFlow","step","index","stepObj","existingStep","__spreadProps","__spreadValues","newSteps","properties","__async","thisStep","copy","clone","STARTED_STEP","isLastStep","COMPLETED_STEP","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","h","STARTED_FLOW","COMPLETED_FLOW","SKIPPED_FLOW","nextStep","NOT_STARTED_FLOW","currentStep","previousFlow","variables","replaceVariables","str","matches","match","variable","key","action","data","stepId","date","flowStatesRaw","callback","NOT_STARTED_STEP","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","LOCAL_STORAGE_PREFIX","cloneFlow","flow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","clearCache","frigadeGlobalState","key","GET_CACHE_PREFIX","resetAllLocalStorage","isWeb","LOCAL_STORAGE_PREFIX","CallQueue","call","now","item","callQueue","gracefulFetch","url","options","__async","_a","getEmptyResponse","lastCallDataKey","response","error","body","e","generateGuestId","guestId","getLocalStorage","GUEST_KEY","GUEST_PREFIX","uuidv4","setLocalStorage","isWeb","RulesGraph","graphData","registry","_a","_b","flowId","callback","currentNode","nodeId","originId","ruleId","node","result","edge","ancestor","Frigade","Fetchable","apiKey","config","__spreadValues","__async","isWeb","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","__spreadProps","groupId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","that","validator","target","key","value","previousState","newState","RulesGraph","overrideFlowStateRaw","_b","_c","flowStateRaw","hasRuleGraphChanged","flowState","f","statefulFlow","Flow","parsed","step"]}
|
|
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/rules-graph.ts","../src/core/frigade.ts"],"sourcesContent":["export const VERSION_NUMBER = '0.2.20'\n","import { VERSION_NUMBER } from '../core/version'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { frigadeGlobalState } from './state'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nconst GUEST_KEY = 'frigade-guest-key'\nexport const GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow({\n config: flow.config,\n id: flow.id,\n })\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n }\n}\n\nfunction setGlobalState(key: string, value: any) {\n frigadeGlobalState[key] = value\n}\n\nfunction getGlobalState(key: string): any {\n return frigadeGlobalState[key]\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nclass CallQueue {\n private queue: {\n call: string\n time: number\n }[] = []\n private readonly ttlInMS = 500\n private readonly cacheSize = 5\n\n public push(call: string) {\n const now = new Date()\n if (this.queue.length >= this.cacheSize) {\n this.queue.shift()\n }\n this.queue.push({\n call: call,\n time: now.getTime(),\n })\n }\n\n public hasIdenticalCall(call: string) {\n const now = new Date()\n this.queue = this.queue.filter((item) => now.getTime() - item.time < this.ttlInMS)\n return this.queue.some((item) => item.call === call)\n }\n}\n\nconst callQueue = new CallQueue()\n\nexport async function gracefulFetch(url: string, options: any) {\n if (typeof globalThis.fetch !== 'function') {\n return getEmptyResponse(\n \"- Attempted to call fetch() in an environment that doesn't support it.\"\n )\n }\n\n if (isWeb() && options && options.body && options.method === 'POST') {\n const lastCallDataKey = `${url}${JSON.stringify(options.body ?? {})}`\n if (callQueue.hasIdenticalCall(lastCallDataKey)) {\n return getEmptyResponse()\n }\n callQueue.push(lastCallDataKey)\n }\n\n let response\n try {\n response = fetch(url, options)\n response = await response\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n if (response.status === 204) {\n return getEmptyResponse()\n }\n\n let body\n try {\n body = await response.json()\n } catch (e) {\n return getEmptyResponse()\n }\n\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nexport function getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n\nexport function isWeb() {\n return (\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.localStorage !== 'undefined'\n )\n}\n","import { FlowStates, FlowStep, FrigadeConfig, StatefulFlow } from '../core/types'\nimport { Flow } from '../core/flow'\nimport { RulesGraph } from '../core/rules-graph'\n\nexport interface FrigadeGlobalState {\n refreshStateFromAPI: (overrideFlowStatesRaw?: FlowStates) => Promise<void>\n flowStates: Record<string, StatefulFlow>\n rulesGraph: RulesGraph\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 variables: Record<string, Record<string, any>>\n lastSyncDate?: Date\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.groupId ?? ''\n }`\n}\n","import { generateGuestId, getEmptyResponse, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../core/types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(12).substring(4),\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(this.getAPIUrl(path), {\n keepalive: true,\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n\n private getAPIUrl(path: string) {\n const pathPrefix = '/v1/public'\n const apiUrl = new URL(\n `${pathPrefix}${path}`,\n this.config.apiUrl.replace(pathPrefix, '')\n ).toString()\n\n return apiUrl\n }\n\n /**\n * @ignore\n */\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade has not yet been initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import {\n FlowActionType,\n FlowStateDTO,\n FlowStates,\n FlowStep,\n FrigadeConfig,\n StatefulFlow,\n StatefulStep,\n} from './types'\nimport {\n clone,\n cloneFlow,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n NOT_STARTED_STEP,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { Fetchable } from '../shared/fetchable'\nimport { RulesGraphRegistryCallback } from './rules-graph'\n\nexport class Flow extends Fetchable {\n /**\n * The Flow's ID.\n */\n public id: string\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The metadata of the Flow.\n * @ignore\n */\n public rawData: StatefulFlow\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 * @ignore\n */\n private _isVisible: boolean = false\n /**\n * Whether the Flow is visible to the user based on the current user/group's state.\n */\n get isVisible() {\n if (this._isVisible === false) {\n return false\n }\n\n return this.getGlobalState().rulesGraph.isFlowVisible(this.id)\n }\n set isVisible(visible: boolean) {\n this._isVisible = visible\n }\n\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n constructor({ config, id }: { config: FrigadeConfig; id: string }) {\n super(config)\n this.id = id\n this.init()\n }\n\n /**\n * Reload the Flow data from the server\n */\n reload() {\n this.init()\n }\n\n /**\n * @ignore\n */\n resyncState(overrideStatefulFlow?: StatefulFlow) {\n const statefulFlow = overrideStatefulFlow ?? this.getStatefulFlow()\n\n this.rawData = statefulFlow\n this.title = statefulFlow?.data?.title\n this.subtitle = statefulFlow?.data?.subtitle\n\n this.isCompleted = statefulFlow.$state.completed\n this.isStarted = statefulFlow.$state.started\n this.isSkipped = statefulFlow.$state.skipped\n this._isVisible = statefulFlow.$state.visible\n\n // Set\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n const existingStep = this.steps?.get(step.id)\n if (existingStep) {\n existingStep.$state = stepObj.$state\n }\n })\n }\n\n /**\n * @ignore\n */\n private initStepFromStatefulStep(step: StatefulStep, index: number) {\n return {\n ...step,\n flow: this,\n $state: {\n ...step.$state,\n lastActionAt: step.$state.lastActionAt ? new Date(step.$state.lastActionAt) : undefined,\n },\n order: index,\n } as Partial<FlowStep>\n }\n\n /**\n * @ignore\n */\n private init() {\n const statefulFlow = this.getStatefulFlow()\n\n this.resyncState()\n\n const newSteps = new Map<string, FlowStep>()\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.$state.started) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n copy.$state.lastActionAt = new Date()\n copy.$state.currentStepId = thisStep.id\n copy.$state.currentStepIndex = thisStep.order\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (!thisStep.$state.completed) {\n await this.sendFlowStateToAPI(STARTED_STEP, properties, thisStep.id)\n }\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const thisStep = this.steps.get(step.id)\n\n if (thisStep.$state.completed) {\n return\n }\n\n const numberOfCompletedSteps = this.getNumberOfCompletedSteps()\n const isLastStep = numberOfCompletedSteps + 1 == this.steps.size\n const copy = clone(this.getGlobalState().flowStates[this.id])\n\n copy.$state.started = true\n copy.data.steps[thisStep.order].$state.completed = true\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n\n // If there are more index, advance current step\n if (!isLastStep) {\n copy.$state.currentStepId = this.getStepByIndex(thisStep.order + 1).id\n copy.$state.currentStepIndex = thisStep.order + 1\n }\n\n if (isLastStep) {\n copy.$state.completed = true\n }\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (isLastStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n\n await this.sendFlowStateToAPI(COMPLETED_STEP, properties, thisStep.id)\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.$state.completed) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = false\n copy.data.steps[thisStep.order].$state.completed = false\n copy.data.steps[thisStep.order].$state.lastActionAt = undefined\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(NOT_STARTED_STEP, undefined, thisStep.id)\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.$state.completed !== previousStep?.$state.completed ||\n thisStep.$state.started !== previousStep?.$state.started ||\n thisStep.$state.visible !== previousStep?.$state.visible ||\n thisStep.$state.blocked !== previousStep?.$state.blocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj as FlowStep)\n })\n this.steps = newSteps\n // Check if empty object\n if (\n this.getGlobalState().variables &&\n this.getGlobalState().variables[this.id] &&\n Object.keys(this.getGlobalState().variables[this.id]).length > 0\n ) {\n this.applyVariables(this.getGlobalState().variables[this.id])\n }\n }\n\n /**\n * Marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.started = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(STARTED_FLOW, properties)\n }\n\n /**\n * Marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n await this.sendFlowStateToAPI(COMPLETED_FLOW, properties)\n }\n\n /**\n * Marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n if (this.isSkipped) {\n return\n }\n this.optimisticallyMarkFlowSkipped()\n await this.sendFlowStateToAPI(SKIPPED_FLOW, properties)\n }\n\n /**\n * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: Record<string | number, any>) {\n const nextStep = this.getStepByIndex(this.getCurrentStepIndex() + 1)\n if (nextStep) {\n await nextStep.start(properties)\n } else {\n await this.complete(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: Record<string | number, any>) {\n const previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n this.optimisticallyMarkFlowNotStarted()\n await this.sendFlowStateToAPI(NOT_STARTED_FLOW)\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Gets current step\n */\n public getCurrentStep(): FlowStep {\n return (\n this.steps.get(this.getStatefulFlow().$state.currentStepId) ??\n this.steps.get(Array.from(this.steps.keys())[0])\n )\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.completed).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.visible).length\n }\n\n /**\n * @ignore\n */\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (flow.id === this.id) {\n if (\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 }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n /**\n * @ignore\n */\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n /**\n * @ignore\n */\n public applyVariables(variables: Record<string, any>) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n if (!variables[variable]) {\n return\n }\n str = str.replace(match, variables[variable])\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n this.steps.forEach((step) => {\n // Iterate over every string field in the step and replace variables\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n }\n })\n })\n\n this.getGlobalState().variables = {}\n this.getGlobalState().variables[this.id] = variables\n }\n\n /**\n * @ignore\n */\n private getStatefulFlow(): StatefulFlow {\n const userFlowStates = this.getGlobalState().flowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowCompleted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = true\n copy.$state.started = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowNotStarted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = false\n copy.$state.started = false\n copy.$state.visible = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n private async sendFlowStateToAPI(\n action: FlowActionType,\n data?: Record<string | number, any>,\n stepId?: string\n ) {\n const date = new Date()\n this.getGlobalState().lastSyncDate = date\n const flowStatesRaw: FlowStates = await this.fetch('/flowStates', {\n method: 'POST',\n body: JSON.stringify({\n userId: this.config.userId,\n groupId: this.config.groupId,\n flowSlug: this.id,\n stepId: stepId ?? this.getCurrentStep().id,\n data: data ? JSON.stringify(data) : {},\n actionType: action,\n createdAt: date,\n } as FlowStateDTO),\n })\n if (date < this.getGlobalState().lastSyncDate) {\n return\n }\n await this.getGlobalState().refreshStateFromAPI(flowStatesRaw)\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowSkipped() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.skipped = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n public register(callback?: RulesGraphRegistryCallback) {\n const globalState = this.getGlobalState()\n\n globalState.rulesGraph.register(this.id, (visible) => {\n const prevFlow = this.getGlobalState().previousFlows.get(this.id)\n\n if (prevFlow?._isVisible !== visible) {\n // TODO: Store these in a hash so we can grab this flow's handler and call it\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n handler(this, prevFlow)\n this.getGlobalState().previousFlows.set(this.id, cloneFlow(this))\n })\n }\n\n callback?.(visible)\n })\n }\n\n public unregister() {\n this.getGlobalState().rulesGraph.unregister(this.id)\n }\n}\n","import { RulesGraphData } from './types'\n\nexport interface RulesGraphNode {\n visible: boolean\n edges: RulesGraphEdge[]\n}\n\nexport interface RulesGraphEdge {\n head: string\n ruleId: string\n}\n\nexport type RulesGraphRegistryCallback = (visible: boolean) => void\n\n// TODO: JSDoc this class\nexport class RulesGraph {\n private graph: Map<string, RulesGraphNode> = new Map()\n private readonly registry: Map<string, RulesGraphRegistryCallback> = new Map()\n private readonly ruleOrder: string[] = []\n\n constructor(graphData: RulesGraphData) {\n this.ruleOrder = graphData?.ruleOrder ?? []\n this.ingestGraphData(graphData?.graph ?? {})\n }\n\n ingestGraphData(graphData: Record<string, RulesGraphNode>) {\n this.graph = new Map(Object.entries(graphData))\n\n this.fireCallbacks()\n }\n\n fireCallbacks() {\n for (const [flowId, callback] of this.registry) {\n if (typeof callback === 'function') {\n callback(this.isFlowVisible(flowId))\n }\n }\n }\n\n isFlowVisible(flowId: string) {\n const currentNode = this.graph.get(flowId)\n\n // Is the flow in the graph?\n // If not, it belongs to 0 rules and can carry on about its business\n if (!currentNode) {\n return true\n }\n\n if (currentNode.visible === false) {\n return false\n }\n\n // Does the flow have edges?\n // If not, it's the king of all flows, and it does what it wants\n if (currentNode.edges.length === 0) {\n return true\n }\n\n // Are any of the flow's descendants visible and in the registry already?\n const registeredDescendant = this.findRegisteredDescendant(flowId)\n\n // If so, this flow is not visible\n if (registeredDescendant != null) {\n return false\n }\n\n // Congrats! There are no conditions in the graph that disqualify this flow from being visible\n return true\n }\n\n register(flowId: string, callback?: RulesGraphRegistryCallback) {\n this.registry.set(flowId, callback ?? (() => {}))\n\n this.fireCallbacks()\n }\n\n unregister(flowId: string) {\n this.registry.delete(flowId)\n\n this.fireCallbacks()\n }\n\n getRegistry() {\n return this.registry\n }\n\n private findRegisteredDescendant(nodeId: string, originId = nodeId, ruleId?: string) {\n const node = this.graph.get(nodeId)\n\n if (node == null) {\n return undefined\n }\n\n if (this.registry.has(nodeId) && originId !== nodeId) {\n return node\n }\n\n let result = undefined\n\n if (node.edges.length > 0) {\n for (const edge of node.edges) {\n // If we went past the end of the rule, stop searching for this rule\n if (ruleId != null && edge.ruleId !== ruleId) {\n continue\n }\n\n const ancestor = this.findRegisteredDescendant(edge.head, originId, ruleId ?? edge.ruleId)\n\n if (ancestor != null && ancestor.visible) {\n result = ancestor\n break\n }\n }\n }\n\n return result\n }\n}\n","import { FlowStates, FrigadeConfig, StatefulFlow, StatefulStep } from './types'\nimport { clearCache, cloneFlow, GUEST_PREFIX, isWeb, resetAllLocalStorage } from '../shared/utils'\nimport { Flow } from './flow'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/fetchable'\nimport { RulesGraph } from './rules-graph'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = async () => {\n if (document.visibilityState === 'visible') {\n await this.refreshStateFromAPI()\n }\n }\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb()) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n }\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\n */\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n if (this.config.userId && !this.config.userId?.startsWith(GUEST_PREFIX)) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n }),\n })\n }\n await this.refreshStateFromAPI()\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.config = { ...this.config, userId }\n await this.initIfNeeded()\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.resync()\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.groupId = groupId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n properties,\n }),\n })\n await this.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.groupId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n } else if (this.config.userId) {\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n events: [\n {\n event,\n properties,\n },\n ],\n }),\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\n */\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n /**\n * Reload the current state of the flows by calling the Frigade API.\n * This will trigger all event handlers.\n */\n public async reload() {\n resetAllLocalStorage()\n clearCache()\n await this.refreshStateFromAPI()\n this.initPromise = null\n await this.init(this.config)\n // Trigger all event handlers\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n private async resync() {\n this.initPromise = null\n await this.init(this.config)\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @param handler\n */\n public async onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\n */\n public async removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n /**\n * @ignore\n */\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n /**\n * @ignore\n */\n private async refreshStateFromAPI(): 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 (target[key]) {\n const previousState = target[key] as StatefulFlow\n const newState = value as StatefulFlow\n if (JSON.stringify(previousState) !== JSON.stringify(newState)) {\n that.triggerEventHandlers(newState, previousState)\n }\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshStateFromAPI: async () => {},\n rulesGraph: new RulesGraph({\n graph: {},\n ruleOrder: [],\n }),\n flowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n variables: {},\n }\n\n if (this.config.__readOnly && this.config.__flowConfigOverrides) {\n this.mockFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshStateFromAPI = async (\n overrideFlowStateRaw?: FlowStates\n ) => {\n if (this.config.__readOnly) {\n return\n }\n\n const flowStateRaw: FlowStates = overrideFlowStateRaw\n ? overrideFlowStateRaw\n : await this.fetch(\n `/flowStates?userId=${encodeURIComponent(this.config.userId)}${\n this.config.groupId ? `&groupId=${encodeURIComponent(this.config.groupId)}` : ''\n }`\n )\n\n // TODO: should this also take in order and check if it has changed?\n frigadeGlobalState[globalStateKey].rulesGraph.ingestGraphData(\n flowStateRaw.ruleGraph?.graph ?? {}\n )\n\n if (flowStateRaw && flowStateRaw.eligibleFlows) {\n flowStateRaw.eligibleFlows.forEach((statefulFlow) => {\n frigadeGlobalState[globalStateKey].flowStates[statefulFlow.flowSlug] = statefulFlow\n if (!this.flows.find((flow) => flow.id == statefulFlow.flowSlug)) {\n this.flows.push(\n new Flow({\n config: this.config,\n id: statefulFlow.flowSlug,\n })\n )\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshStateFromAPI()\n }\n\n /**\n * @ignore\n */\n private mockFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowConfigOverrides).forEach((flowId) => {\n const parsed = JSON.parse(this.config.__flowConfigOverrides[flowId])\n frigadeGlobalState[globalStateKey].flowStates[flowId] = {\n flowSlug: flowId,\n flowName: parsed?.name ?? flowId,\n flowType: parsed?.type ?? 'CHECKLIST',\n data: {\n ...parsed,\n steps: (parsed?.steps ?? []).map((step: any): StatefulStep => {\n return {\n id: step.id,\n $state: {\n completed: false,\n started: false,\n visible: true,\n blocked: false,\n },\n ...step,\n }\n }),\n },\n $state: {\n currentStepId: null,\n currentStepIndex: -1,\n completed: false,\n started: false,\n skipped: false,\n visible: true,\n },\n } as StatefulFlow\n\n this.flows.push(\n new Flow({\n config: this.config,\n id: flowId,\n })\n )\n })\n }\n\n /**\n * @ignore\n */\n private async triggerEventHandlers(newState: StatefulFlow, previousState?: StatefulFlow) {\n if (newState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousState.flowSlug) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(newState)\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","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","_a","_b","Fetchable","config","generateGuestId","filteredConfig","_","v","__spreadValues","path","options","__async","getEmptyResponse","gracefulFetch","getHeaders","pathPrefix","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","id","visible","overrideStatefulFlow","_a","_b","statefulFlow","step","index","stepObj","existingStep","__spreadProps","__spreadValues","newSteps","properties","__async","thisStep","copy","clone","STARTED_STEP","isLastStep","COMPLETED_STEP","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","h","STARTED_FLOW","COMPLETED_FLOW","SKIPPED_FLOW","nextStep","NOT_STARTED_FLOW","currentStep","previousFlow","variables","replaceVariables","str","matches","match","variable","key","action","data","stepId","date","flowStatesRaw","callback","prevFlow","cloneFlow","NOT_STARTED_STEP","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","LOCAL_STORAGE_PREFIX","cloneFlow","flow","Flow","clone","obj","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","isWeb","setLocalStorage","value","clearCache","frigadeGlobalState","key","GET_CACHE_PREFIX","resetAllLocalStorage","isWeb","LOCAL_STORAGE_PREFIX","CallQueue","call","now","item","callQueue","gracefulFetch","url","options","__async","_a","getEmptyResponse","lastCallDataKey","response","error","body","e","generateGuestId","guestId","getLocalStorage","GUEST_KEY","GUEST_PREFIX","uuidv4","setLocalStorage","isWeb","RulesGraph","graphData","_a","_b","flowId","callback","currentNode","nodeId","originId","ruleId","node","result","edge","ancestor","Frigade","Fetchable","apiKey","config","__spreadValues","__async","isWeb","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","__spreadProps","groupId","event","flowId","flow","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","that","validator","target","key","value","previousState","newState","RulesGraph","overrideFlowStateRaw","_b","flowStateRaw","statefulFlow","Flow","_c","parsed","step"]}
|