@frigade/js 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,12 +37,12 @@ npm install @frigade/js
37
37
 
38
38
  ## Usage
39
39
 
40
- Simply `import frigade from '@frigade/js'` and use it. Example:
40
+ Simply `import { Frigade } from '@frigade/js'` and use it. Example:
41
41
 
42
42
  ```js
43
- import frigade from 'packages/js-api'
43
+ import { Frigade } from 'packages/js-api'
44
44
 
45
- await frigade.init('FRIGADE_API_KEY')
45
+ const frigade = new Frigade('FRIGADE_API_KEY')
46
46
 
47
47
  await frigade.identify('USER_ID', {
48
48
  name: 'USER_NAME',
@@ -62,7 +62,7 @@ await frigade.group('ORGANIZATION_ID', {
62
62
 
63
63
  ```js
64
64
  const flow = await frigade.getFlow('FLOW_ID')
65
- // Flow data defined in flow-data.yml in the Frigade dashboard
65
+ // Flow data defined in config.yml in the Frigade dashboard
66
66
  console.log('Flow status:', flow.isCompleted)
67
67
  console.log('Flow data:', flow.rawData)
68
68
  ```
package/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ interface InternalConfig {
16
16
  apiKey: string;
17
17
  userId?: string;
18
18
  organizationId?: string;
19
+ __instanceId?: string;
19
20
  }
20
21
 
21
22
  interface FlowDataRaw {
@@ -58,6 +59,10 @@ interface FlowStep {
58
59
  * Unique identifier for the step.
59
60
  */
60
61
  id: string;
62
+ /**
63
+ * Order of the step in the flow.
64
+ */
65
+ order: number;
61
66
  /**
62
67
  * Name of the step when shown in a list view
63
68
  */
@@ -125,11 +130,11 @@ interface FlowStep {
125
130
  /**
126
131
  * Whether the step is blocked (can't be accessed yet) based on `startCriteria`
127
132
  */
128
- blocked?: boolean;
133
+ isBlocked: boolean;
129
134
  /**
130
135
  * Whether the step is hidden (not shown in the list view) based on `visibilityCriteria`
131
136
  */
132
- hidden?: boolean;
137
+ isHidden: boolean;
133
138
  props?: any;
134
139
  /**
135
140
  * Criteria that needs to be met for the step to complete
@@ -148,7 +153,7 @@ interface FlowStep {
148
153
  */
149
154
  dismissible?: boolean;
150
155
  /**
151
- * Any other additional props defined in flow-data.yml
156
+ * Any other additional props defined in config.yml
152
157
  */
153
158
  [x: string | number | symbol]: unknown;
154
159
  /**
@@ -167,19 +172,19 @@ declare class Flow {
167
172
  */
168
173
  id: string;
169
174
  /**
170
- * The raw data defined in `flow-data.yml` as a JSON decoded object
175
+ * The raw data defined in `config.yml` as a JSON decoded object
171
176
  */
172
177
  rawData: Record<any, any>;
173
178
  /**
174
- * The steps contained in the `data` array in `flow-data.yml`
179
+ * Ordered map from Step ID to step data. The `steps` array in `config.yml`
175
180
  */
176
- steps: FlowStep[];
181
+ steps: Record<string, FlowStep>;
177
182
  /**
178
- * The user-facing title of the flow, if defined at the top level of `flow-data.yml`
183
+ * The user-facing title of the flow, if defined at the top level of `config.yml`
179
184
  */
180
185
  title?: string;
181
186
  /**
182
- * The user-facing description of the flow, if defined at the top level of `flow-data.yml`
187
+ * The user-facing description of the flow, if defined at the top level of `config.yml`
183
188
  */
184
189
  subtitle?: string;
185
190
  /**
@@ -214,6 +219,11 @@ declare class Flow {
214
219
  * Get a step by id
215
220
  */
216
221
  getStep(id: string): FlowStep | undefined;
222
+ /**
223
+ * Get a step by index
224
+ * @param index
225
+ */
226
+ getStepByIndex(index: number): FlowStep | undefined;
217
227
  /**
218
228
  * Function that gets current step index
219
229
  */
@@ -229,19 +239,20 @@ declare class Frigade {
229
239
  private config?;
230
240
  private hasInitialized;
231
241
  private internalConfig?;
242
+ private __instanceId;
232
243
  private flows;
233
- init(apiKey: string, config?: FrigadeConfig): Promise<void>;
244
+ constructor(apiKey: string, config?: FrigadeConfig);
245
+ private init;
234
246
  identify(userId: string, properties?: Record<string, any>): Promise<void>;
235
247
  group(organizationId: string, properties?: Record<string, any>): Promise<void>;
236
248
  track(event: string, properties?: Record<string, any>): Promise<void>;
237
249
  getFlow(flowId: string): Promise<Flow>;
238
250
  getFlows(): Promise<Flow[]>;
239
251
  reset(): Promise<void>;
240
- private errorOnUninitialized;
252
+ private initIfNeeded;
241
253
  private refreshUserFlowStates;
242
254
  private refreshFlows;
243
255
  private refreshInternalConfig;
244
256
  }
245
- declare const frigade: Frigade;
246
257
 
247
- export { Flow, frigade as default };
258
+ export { Flow, Frigade };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- var A=Object.create;var h=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var v=Object.getPrototypeOf,z=Object.prototype.hasOwnProperty;var K=(i,t)=>{for(var e in t)h(i,e,{get:t[e],enumerable:!0})},O=(i,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of x(t))!z.call(i,a)&&a!==e&&h(i,a,{get:()=>t[a],enumerable:!(r=L(t,a))||r.enumerable});return i};var N=(i,t,e)=>(e=i!=null?A(v(i)):{},O(t||!i||!i.__esModule?h(e,"default",{value:i,enumerable:!0}):e,i)),G=i=>O(h({},"__esModule",{value:!0}),i);var V={};K(V,{Flow:()=>d,default:()=>j});module.exports=G(V);var D="0.0.6";var b=N(require("cross-fetch")),R=require("uuid");var T="COMPLETED_FLOW";var I="STARTED_FLOW",U="NOT_STARTED_FLOW",S="COMPLETED_STEP",g="STARTED_STEP",W="frigade-last-call-at-",J="frigade-last-call-data-",C="frigade-guest-key",M="guest_";function $(i){return{config:{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json","X-Frigade-SDK-Version":D,"X-Frigade-SDK-Platform":"Javascript"}}}}function y(i){return window&&window.localStorage?window.localStorage.getItem(i):null}function E(i,t){window&&window.localStorage&&window.localStorage.setItem(i,t)}function _(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(i=>{i.startsWith("frigade-")&&window.localStorage.removeItem(i)})}async function k(i,t){let e=W+i,r=J+i;if(window&&window.localStorage&&t&&t.body&&t.method==="POST"){let s=y(e),f=y(r);if(s&&f&&f==t.body){let n=new Date(s);if(new Date().getTime()-n.getTime()<1e3)return u()}E(e,new Date().toISOString()),E(r,t.body)}let a;try{a=await(0,b.default)(i,t)}catch(s){return u(s)}return a?a.staus>=400?u(a.statusText):a.json():u()}function u(i){return i&&console.log("Call to Frigade failed",i),{json:()=>({})}}function F(){if(window&&window.localStorage){let i=y(C);return i||(i=`${M}${(0,R.v4)()}`,window.localStorage.setItem(C,i)),i}}function o(i,t,e){return k(`//api.frigade.com/v1/public${t}`,{...e??{},...$(i).config})}var l={};function p(i){return`${i.apiKey}:${i.userId??""}:${i.organizationId??""}`}var d=class{constructor(t,e){this.internalConfig=t,this.flowDataRaw=e,this.initFromRawData(e)}initFromRawData(t){let e=JSON.parse(t.data),r=e.data;this.id=t.slug,this.metadata=t,this.rawData=e,this.title=this.rawData.title,this.subtitle=this.rawData.subtitle;let a=this.getUserFlowState();this.isCompleted=a.flowState==T,this.isStarted=a.flowState==I,this.steps=[...r.map(s=>{let f=a.stepStates[s.id],n={...s,isCompleted:f.actionType==S,isStarted:f.actionType==g};return n.start=async c=>{n.isCompleted=!0,await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:s.id,data:c??{},createdAt:new Date().toISOString(),actionType:g})}),await this.refreshUserFlowState();let w=this.getUserFlowState();n.isCompleted=w.stepStates[s.id].actionType==S,n.isStarted=w.stepStates[s.id].actionType==g},n.complete=async c=>{n.isCompleted=!0,await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:s.id,data:c??{},createdAt:new Date().toISOString(),actionType:S})}),await this.refreshUserFlowState();let w=this.getUserFlowState();n.isCompleted=w.stepStates[s.id].actionType==S,n.isStarted=w.stepStates[s.id].actionType==g},n})]}async start(t){let e=this.getCurrentStepIndex(),r=e!=-1?this.steps[e].id:"unknown";await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:r,data:t??{},createdAt:new Date().toISOString(),actionType:I})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){let e=this.getCurrentStepIndex(),r=e!=-1?this.steps[e].id:"unknown";await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:r,data:t??{},createdAt:new Date().toISOString(),actionType:T})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:U})})}getStep(t){return this.steps.find(e=>e.id==t)}getCurrentStepIndex(){let t=this.getUserFlowState();if(!t)return 0;let e=t.lastStepId,r=this.steps.findIndex(a=>a.id===e);return r==-1?0:r}getUserFlowState(){return l[p(this.internalConfig)].userFlowStates[this.id]}async refreshUserFlowState(){await l[p(this.internalConfig)].refreshUserFlowStates()}};var m=class{constructor(){this.userId=F();this.hasInitialized=!1;this.flows=[]}async init(t,e){this.apiKey=t,this.config=e,e!=null&&e.userId&&(this.userId=e.userId),e!=null&&e.organizationId&&(this.organizationId=e.organizationId),this.refreshInternalConfig(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.hasInitialized=!0}async identify(t,e){this.errorOnUninitialized(),this.userId=t,this.refreshInternalConfig(),await o(this.apiKey,"/users",{method:"POST",body:JSON.stringify({foreignId:this.userId,properties:e})}),await this.refreshUserFlowStates()}async group(t,e){this.errorOnUninitialized(),this.organizationId=t,this.refreshInternalConfig(),await o(this.apiKey,"/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.userId,foreignUserGroupId:this.organizationId,properties:e})}),await this.refreshUserFlowStates()}async track(t,e){this.errorOnUninitialized(),await o(this.apiKey,"/track",{method:"POST",body:JSON.stringify({foreignUserId:this.userId,foreignUserGroupId:this.organizationId,event:t,properties:e})})}async getFlow(t){return this.errorOnUninitialized(),this.flows.find(e=>e.id==t)}async getFlows(){return this.errorOnUninitialized(),this.flows}async reset(){_(),this.userId=F(),this.organizationId=void 0}errorOnUninitialized(){if(!this.hasInitialized)throw new Error("Frigade has not been initialized yet. Please call Frigade.init() before using any other methods.")}async refreshUserFlowStates(){let t=p(this.internalConfig);l[t]={refreshUserFlowStates:async()=>{},userFlowStates:{}},l[t].refreshUserFlowStates=async()=>{let e=await o(this.apiKey,`/userFlowStates?foreignUserId=${this.userId}${this.organizationId?`&foreignUserGroupId=${this.organizationId}`:""}`);e&&e.data&&e.data.forEach(a=>{l[t].userFlowStates[a.flowId]=a})},await l[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await o(this.apiKey,"/flows");t&&t.data&&t.data.forEach(r=>{this.flows.push(new d(this.internalConfig,r))})}refreshInternalConfig(){this.internalConfig={apiKey:this.apiKey,userId:this.userId,organizationId:this.organizationId}}},B=new m,P=B;var j=P;0&&(module.exports={Flow});
2
+ var A=Object.create;var u=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var K=(i,t)=>{for(var e in t)u(i,e,{get:t[e],enumerable:!0})},D=(i,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of v(t))!N.call(i,a)&&a!==e&&u(i,a,{get:()=>t[a],enumerable:!(r=L(t,a))||r.enumerable});return i};var z=(i,t,e)=>(e=i!=null?A(x(i)):{},D(t||!i||!i.__esModule?u(e,"default",{value:i,enumerable:!0}):e,i)),G=i=>D(u({},"__esModule",{value:!0}),i);var B={};K(B,{Flow:()=>d,Frigade:()=>y});module.exports=G(B);var C="0.1.0";var R=z(require("cross-fetch")),_=require("uuid");var F="COMPLETED_FLOW";var m="STARTED_FLOW",U="NOT_STARTED_FLOW",p="COMPLETED_STEP",S="STARTED_STEP",W="frigade-last-call-at-",M="frigade-last-call-data-",E="frigade-guest-key",$="guest_";function J(i){return{config:{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json","X-Frigade-SDK-Version":C,"X-Frigade-SDK-Platform":"Javascript"}}}}function T(i){return window&&window.localStorage?window.localStorage.getItem(i):null}function b(i,t){window&&window.localStorage&&window.localStorage.setItem(i,t)}function P(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(i=>{i.startsWith("frigade-")&&window.localStorage.removeItem(i)})}async function k(i,t){let e=W+i,r=M+i;if(window&&window.localStorage&&t&&t.body&&t.method==="POST"){let s=T(e),g=T(r);if(s&&g&&g==t.body){let f=new Date(s);if(new Date().getTime()-f.getTime()<1e3)return I()}b(e,new Date().toISOString()),b(r,t.body)}let a;try{a=await(0,R.default)(i,t)}catch(s){return I(s)}return a?a.staus>=400?I(a.statusText):a.json():I()}function I(i){return i&&console.log("Call to Frigade failed",i),{json:()=>({})}}function O(){if(typeof window<"u"&&typeof window.localStorage<"u"){let i=T(E);return i||(i=`${$}${(0,_.v4)()}`,window.localStorage.setItem(E,i)),i}}function o(i,t,e){return k(`//api.frigade.com/v1/public${t}`,{...e??{},...J(i).config})}var l={};function c(i){return`${i.__instanceId}-${i.apiKey}:${i.userId??""}:${i.organizationId??""}`}var d=class{constructor(t,e){this.internalConfig=t,this.flowDataRaw=e,this.initFromRawData(e)}initFromRawData(t){let e=JSON.parse(t.data),r=e.steps??e.data??[];this.id=t.slug,this.metadata=t,this.rawData=e,this.title=this.rawData.title,this.subtitle=this.rawData.subtitle;let a=this.getUserFlowState();this.isCompleted=a.flowState==F,this.isStarted=a.flowState==m,this.steps={},r.forEach((s,g)=>{let f=a.stepStates[s.id],n={...s,isCompleted:f.actionType==p,isStarted:f.actionType==S,isHidden:f.hidden,isBlocked:f.blocked,order:g};n.start=async h=>{n.isCompleted=!0,await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:s.id,data:h??{},createdAt:new Date().toISOString(),actionType:S})}),await this.refreshUserFlowState();let w=this.getUserFlowState();n.isCompleted=w.stepStates[s.id].actionType==p,n.isStarted=w.stepStates[s.id].actionType==S},n.complete=async h=>{n.isCompleted=!0,await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:s.id,data:h??{},createdAt:new Date().toISOString(),actionType:p})}),await this.refreshUserFlowState();let w=this.getUserFlowState();n.isCompleted=w.stepStates[s.id].actionType==p,n.isStarted=w.stepStates[s.id].actionType==S},this.steps[s.id]=n})}async start(t){let e=this.getCurrentStepIndex(),r=e!=-1?this.steps[e].id:"unknown";await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:r,data:t??{},createdAt:new Date().toISOString(),actionType:m})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){let e=this.getCurrentStepIndex(),r=e!=-1?this.getStepByIndex(e).id:"unknown";await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:r,data:t??{},createdAt:new Date().toISOString(),actionType:F})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:U})})}getStep(t){return this.steps[t]}getStepByIndex(t){return this.steps[Object.keys(this.steps)[t]]}getCurrentStepIndex(){var r;let t=this.getUserFlowState();if(!t)return 0;let e=t.lastStepId;return((r=this.steps[e])==null?void 0:r.order)??0}getUserFlowState(){return l[c(this.internalConfig)].userFlowStates[this.id]}async refreshUserFlowState(){await l[c(this.internalConfig)].refreshUserFlowStates()}};var y=class{constructor(t,e){this.userId=O();this.hasInitialized=!1;this.__instanceId="";this.flows=[];this.__instanceId=Math.random().toString(36).substring(7),this.init(t,e)}async init(t,e){this.apiKey=t,this.config=e,e!=null&&e.userId&&(this.userId=e.userId),e!=null&&e.organizationId&&(this.organizationId=e.organizationId),this.refreshInternalConfig(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.hasInitialized=!0}async identify(t,e){await this.initIfNeeded(),this.userId=t,this.refreshInternalConfig(),await o(this.apiKey,"/users",{method:"POST",body:JSON.stringify({foreignId:this.userId,properties:e})}),await this.refreshUserFlowStates()}async group(t,e){await this.initIfNeeded(),this.organizationId=t,this.refreshInternalConfig(),await o(this.apiKey,"/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.userId,foreignUserGroupId:this.organizationId,properties:e})}),await this.refreshUserFlowStates()}async track(t,e){await this.initIfNeeded(),await o(this.apiKey,"/track",{method:"POST",body:JSON.stringify({foreignUserId:this.userId,foreignUserGroupId:this.organizationId,event:t,properties:e})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){P(),this.userId=O(),this.organizationId=void 0}async initIfNeeded(){this.hasInitialized||await this.init(this.apiKey,this.config)}async refreshUserFlowStates(){let t=c(this.internalConfig);l[t]={refreshUserFlowStates:async()=>{},userFlowStates:{}},l[t].refreshUserFlowStates=async()=>{let e=await o(this.apiKey,`/userFlowStates?foreignUserId=${this.userId}${this.organizationId?`&foreignUserGroupId=${this.organizationId}`:""}`);e&&e.data&&e.data.forEach(a=>{l[t].userFlowStates[a.flowId]=a})},await l[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await o(this.apiKey,"/flows");t&&t.data&&t.data.forEach(r=>{this.flows.push(new d(this.internalConfig,r))})}refreshInternalConfig(){this.internalConfig={apiKey:this.apiKey,userId:this.userId,organizationId:this.organizationId,__instanceId:this.__instanceId}}};0&&(module.exports={Flow,Frigade});
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["import frigade from './core/frigade'\nimport Flow from './core/flow'\n\nexport { Flow }\n\nexport default frigade\n","export const VERSION_NUMBER = '0.0.6'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const ABORTED_FLOW = 'ABORTED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'ABORTED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\n\nfunction getConfig(apiKey: string) {\n return {\n config: {\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}\n\nfunction getLocalStorage(key: string) {\n if (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (window && window.localStorage && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (window && window.localStorage) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getConfig(apiKey).config,\n })\n}\n","import { InternalConfig, UserFlowState } from '../types'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: InternalConfig): string {\n return `${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.organizationId ?? ''\n }`\n}\n","import { InternalConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n COMPLETED_FLOW,\n COMPLETED_STEP,\n fetcher,\n NOT_STARTED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\n\nexport default class Flow {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `flow-data.yml` as a JSON decoded object\n */\n public rawData: Record<any, any>\n /**\n * The steps contained in the `data` array in `flow-data.yml`\n */\n public steps: FlowStep[]\n /**\n * The user-facing title of the flow, if defined at the top level of `flow-data.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `flow-data.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public metadata: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n\n private flowDataRaw: FlowDataRaw\n\n private internalConfig: InternalConfig\n\n constructor(internalConfig: InternalConfig, flowDataRaw: FlowDataRaw) {\n this.internalConfig = internalConfig\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.data\n this.id = flowDataRaw.slug\n this.metadata = flowDataRaw\n this.rawData = flowDataYml\n this.title = this.rawData.title\n this.subtitle = this.rawData.subtitle\n\n const userFlowState = this.getUserFlowState()\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.steps = [\n ...steps.map((step) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n stepObj.isCompleted = true\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: step.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n const updatedUserFlowState = this.getUserFlowState()\n stepObj.isCompleted =\n updatedUserFlowState.stepStates[step.id].actionType == COMPLETED_STEP\n stepObj.isStarted = updatedUserFlowState.stepStates[step.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n stepObj.isCompleted = true\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: step.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n const updatedUserFlowState = this.getUserFlowState()\n stepObj.isCompleted =\n updatedUserFlowState.stepStates[step.id].actionType == COMPLETED_STEP\n stepObj.isStarted = updatedUserFlowState.stepStates[step.id].actionType == STARTED_STEP\n }\n\n return stepObj\n }),\n ]\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n const currentStepIndex = this.getCurrentStepIndex()\n const currentStepId = currentStepIndex != -1 ? this.steps[currentStepIndex].id : 'unknown'\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: currentStepId,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n const currentStepIndex = this.getCurrentStepIndex()\n const currentStepId = currentStepIndex != -1 ? this.steps[currentStepIndex].id : 'unknown'\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: currentStepId,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n }\n\n /**\n * Get a step by id\n */\n public getStep(id: string): FlowStep | undefined {\n return this.steps.find((step) => step.id == id)\n }\n\n /**\n * Function that gets current step index\n */\n public getCurrentStepIndex(): number {\n // Find the userFlowState with most recent timestamp\n const userFlowState = this.getUserFlowState()\n if (!userFlowState) {\n return 0\n }\n const currentStepId = userFlowState.lastStepId\n const index = this.steps.findIndex((step) => step.id === currentStepId)\n return index == -1 ? 0 : index\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = frigadeGlobalState[getGlobalStateKey(this.internalConfig)].userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await frigadeGlobalState[getGlobalStateKey(this.internalConfig)].refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, InternalConfig, UserFlowState } from '../types'\nimport { fetcher, generateGuestId, resetAllLocalStorage } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\n\nexport class Frigade {\n private apiKey?: string\n private userId: string = generateGuestId()\n private organizationId?: string\n private config?: FrigadeConfig\n private hasInitialized = false\n private internalConfig?: InternalConfig\n\n private flows: Flow[] = []\n\n public async init(apiKey: string, config?: FrigadeConfig): Promise<void> {\n this.apiKey = apiKey\n this.config = config\n if (config?.userId) {\n this.userId = config.userId\n }\n if (config?.organizationId) {\n this.organizationId = config.organizationId\n }\n this.refreshInternalConfig()\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n this.hasInitialized = true\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.errorOnUninitialized()\n this.userId = userId\n this.refreshInternalConfig()\n await fetcher(this.apiKey, '/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n this.errorOnUninitialized()\n this.organizationId = organizationId\n this.refreshInternalConfig()\n await fetcher(this.apiKey, '/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.userId,\n foreignUserGroupId: this.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n this.errorOnUninitialized()\n await fetcher(this.apiKey, '/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.userId,\n foreignUserGroupId: this.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n this.errorOnUninitialized()\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n this.errorOnUninitialized()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.userId = generateGuestId()\n this.organizationId = undefined\n }\n\n private errorOnUninitialized() {\n if (!this.hasInitialized) {\n throw new Error(\n 'Frigade has not been initialized yet. Please call Frigade.init() before using any other methods.'\n )\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.internalConfig)\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: {},\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await fetcher(\n this.apiKey,\n `/userFlowStates?foreignUserId=${this.userId}${\n this.organizationId ? `&foreignUserGroupId=${this.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await fetcher(this.apiKey, '/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.internalConfig, flowData))\n })\n }\n }\n\n private refreshInternalConfig() {\n this.internalConfig = {\n apiKey: this.apiKey,\n userId: this.userId,\n organizationId: this.organizationId,\n }\n }\n}\n\nconst frigade = new Frigade()\nexport default frigade\n"],"mappings":"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","names":["src_exports","__export","Flow","src_default","__toCommonJS","VERSION_NUMBER","import_cross_fetch","import_uuid","COMPLETED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","getConfig","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","fetcher","path","frigadeGlobalState","getGlobalStateKey","internalConfig","Flow","internalConfig","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","step","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","fetcher","updatedUserFlowState","currentStepIndex","currentStepId","NOT_STARTED_FLOW","id","index","frigadeGlobalState","getGlobalStateKey","Frigade","generateGuestId","apiKey","config","userId","properties","fetcher","organizationId","event","flowId","flow","resetAllLocalStorage","globalStateKey","getGlobalStateKey","frigadeGlobalState","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","frigade","frigade_default","src_default","frigade_default"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["import { Frigade } from './core/frigade'\nimport Flow from './core/flow'\n\nexport { Flow }\n\nexport { Frigade }\n","export const VERSION_NUMBER = '0.1.0'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const ABORTED_FLOW = 'ABORTED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'ABORTED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\n\nfunction getConfig(apiKey: string) {\n return {\n config: {\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}\n\nfunction getLocalStorage(key: string) {\n if (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (window && window.localStorage && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getConfig(apiKey).config,\n })\n}\n","import { InternalConfig, UserFlowState } from '../types'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: InternalConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.organizationId ?? ''\n }`\n}\n","import { InternalConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n COMPLETED_FLOW,\n COMPLETED_STEP,\n fetcher,\n NOT_STARTED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\n\nexport default class Flow {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public rawData: Record<any, any>\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Record<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public metadata: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n\n private flowDataRaw: FlowDataRaw\n\n private internalConfig: InternalConfig\n\n constructor(internalConfig: InternalConfig, flowDataRaw: FlowDataRaw) {\n this.internalConfig = internalConfig\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.metadata = flowDataRaw\n this.rawData = flowDataYml\n this.title = this.rawData.title\n this.subtitle = this.rawData.subtitle\n\n const userFlowState = this.getUserFlowState()\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.steps = {}\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n stepObj.isCompleted = true\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: step.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n const updatedUserFlowState = this.getUserFlowState()\n stepObj.isCompleted = updatedUserFlowState.stepStates[step.id].actionType == COMPLETED_STEP\n stepObj.isStarted = updatedUserFlowState.stepStates[step.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n stepObj.isCompleted = true\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: step.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n const updatedUserFlowState = this.getUserFlowState()\n stepObj.isCompleted = updatedUserFlowState.stepStates[step.id].actionType == COMPLETED_STEP\n stepObj.isStarted = updatedUserFlowState.stepStates[step.id].actionType == STARTED_STEP\n }\n\n this.steps[step.id] = stepObj\n })\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n const currentStepIndex = this.getCurrentStepIndex()\n const currentStepId = currentStepIndex != -1 ? this.steps[currentStepIndex].id : 'unknown'\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: currentStepId,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n const currentStepIndex = this.getCurrentStepIndex()\n const currentStepId =\n currentStepIndex != -1 ? this.getStepByIndex(currentStepIndex).id : 'unknown'\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: currentStepId,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n }\n\n /**\n * Get a step by id\n */\n public getStep(id: string): FlowStep | undefined {\n return this.steps[id]\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps[Object.keys(this.steps)[index]]\n }\n\n /**\n * Function that gets current step index\n */\n public getCurrentStepIndex(): number {\n // Find the userFlowState with most recent timestamp\n const userFlowState = this.getUserFlowState()\n if (!userFlowState) {\n return 0\n }\n const currentStepId = userFlowState.lastStepId\n return this.steps[currentStepId]?.order ?? 0\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = frigadeGlobalState[getGlobalStateKey(this.internalConfig)].userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await frigadeGlobalState[getGlobalStateKey(this.internalConfig)].refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, InternalConfig, UserFlowState } from '../types'\nimport { fetcher, generateGuestId, resetAllLocalStorage } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\n\nexport class Frigade {\n private apiKey?: string\n private userId: string = generateGuestId()\n private organizationId?: string\n private config?: FrigadeConfig\n private hasInitialized = false\n private internalConfig?: InternalConfig\n private __instanceId = ''\n\n private flows: Flow[] = []\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n this.__instanceId = Math.random().toString(36).substring(7)\n this.init(apiKey, config)\n }\n\n private async init(apiKey: string, config?: FrigadeConfig): Promise<void> {\n this.apiKey = apiKey\n this.config = config\n if (config?.userId) {\n this.userId = config.userId\n }\n if (config?.organizationId) {\n this.organizationId = config.organizationId\n }\n this.refreshInternalConfig()\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n this.hasInitialized = true\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.userId = userId\n this.refreshInternalConfig()\n await fetcher(this.apiKey, '/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.organizationId = organizationId\n this.refreshInternalConfig()\n await fetcher(this.apiKey, '/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.userId,\n foreignUserGroupId: this.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await fetcher(this.apiKey, '/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.userId,\n foreignUserGroupId: this.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.userId = generateGuestId()\n this.organizationId = undefined\n }\n\n private async initIfNeeded() {\n if (!this.hasInitialized) {\n await this.init(this.apiKey, this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.internalConfig)\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: {},\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await fetcher(\n this.apiKey,\n `/userFlowStates?foreignUserId=${this.userId}${\n this.organizationId ? `&foreignUserGroupId=${this.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await fetcher(this.apiKey, '/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.internalConfig, flowData))\n })\n }\n }\n\n private refreshInternalConfig() {\n this.internalConfig = {\n apiKey: this.apiKey,\n userId: this.userId,\n organizationId: this.organizationId,\n __instanceId: this.__instanceId,\n }\n }\n}\n"],"mappings":"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","names":["src_exports","__export","Flow","Frigade","__toCommonJS","VERSION_NUMBER","import_cross_fetch","import_uuid","COMPLETED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","getConfig","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","fetcher","path","frigadeGlobalState","getGlobalStateKey","internalConfig","Flow","internalConfig","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","fetcher","updatedUserFlowState","currentStepIndex","currentStepId","NOT_STARTED_FLOW","id","_a","frigadeGlobalState","getGlobalStateKey","Frigade","apiKey","config","generateGuestId","userId","properties","fetcher","organizationId","event","flowId","flow","resetAllLocalStorage","globalStateKey","getGlobalStateKey","frigadeGlobalState","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow"]}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- var m="0.0.6";import R from"cross-fetch";import{v4 as U}from"uuid";var y="COMPLETED_FLOW";var T="STARTED_FLOW",C="NOT_STARTED_FLOW",S="COMPLETED_STEP",g="STARTED_STEP",_="frigade-last-call-at-",P="frigade-last-call-data-",O="frigade-guest-key",A="guest_";function L(i){return{config:{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json","X-Frigade-SDK-Version":m,"X-Frigade-SDK-Platform":"Javascript"}}}}function u(i){return window&&window.localStorage?window.localStorage.getItem(i):null}function D(i,t){window&&window.localStorage&&window.localStorage.setItem(i,t)}function E(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(i=>{i.startsWith("frigade-")&&window.localStorage.removeItem(i)})}async function x(i,t){let e=_+i,a=P+i;if(window&&window.localStorage&&t&&t.body&&t.method==="POST"){let s=u(e),f=u(a);if(s&&f&&f==t.body){let n=new Date(s);if(new Date().getTime()-n.getTime()<1e3)return h()}D(e,new Date().toISOString()),D(a,t.body)}let r;try{r=await R(i,t)}catch(s){return h(s)}return r?r.staus>=400?h(r.statusText):r.json():h()}function h(i){return i&&console.log("Call to Frigade failed",i),{json:()=>({})}}function I(){if(window&&window.localStorage){let i=u(O);return i||(i=`${A}${U()}`,window.localStorage.setItem(O,i)),i}}function o(i,t,e){return x(`//api.frigade.com/v1/public${t}`,{...e??{},...L(i).config})}var l={};function p(i){return`${i.apiKey}:${i.userId??""}:${i.organizationId??""}`}var w=class{constructor(t,e){this.internalConfig=t,this.flowDataRaw=e,this.initFromRawData(e)}initFromRawData(t){let e=JSON.parse(t.data),a=e.data;this.id=t.slug,this.metadata=t,this.rawData=e,this.title=this.rawData.title,this.subtitle=this.rawData.subtitle;let r=this.getUserFlowState();this.isCompleted=r.flowState==y,this.isStarted=r.flowState==T,this.steps=[...a.map(s=>{let f=r.stepStates[s.id],n={...s,isCompleted:f.actionType==S,isStarted:f.actionType==g};return n.start=async c=>{n.isCompleted=!0,await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:s.id,data:c??{},createdAt:new Date().toISOString(),actionType:g})}),await this.refreshUserFlowState();let d=this.getUserFlowState();n.isCompleted=d.stepStates[s.id].actionType==S,n.isStarted=d.stepStates[s.id].actionType==g},n.complete=async c=>{n.isCompleted=!0,await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:s.id,data:c??{},createdAt:new Date().toISOString(),actionType:S})}),await this.refreshUserFlowState();let d=this.getUserFlowState();n.isCompleted=d.stepStates[s.id].actionType==S,n.isStarted=d.stepStates[s.id].actionType==g},n})]}async start(t){let e=this.getCurrentStepIndex(),a=e!=-1?this.steps[e].id:"unknown";await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:a,data:t??{},createdAt:new Date().toISOString(),actionType:T})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){let e=this.getCurrentStepIndex(),a=e!=-1?this.steps[e].id:"unknown";await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:a,data:t??{},createdAt:new Date().toISOString(),actionType:y})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:C})})}getStep(t){return this.steps.find(e=>e.id==t)}getCurrentStepIndex(){let t=this.getUserFlowState();if(!t)return 0;let e=t.lastStepId,a=this.steps.findIndex(r=>r.id===e);return a==-1?0:a}getUserFlowState(){return l[p(this.internalConfig)].userFlowStates[this.id]}async refreshUserFlowState(){await l[p(this.internalConfig)].refreshUserFlowStates()}};var F=class{constructor(){this.userId=I();this.hasInitialized=!1;this.flows=[]}async init(t,e){this.apiKey=t,this.config=e,e!=null&&e.userId&&(this.userId=e.userId),e!=null&&e.organizationId&&(this.organizationId=e.organizationId),this.refreshInternalConfig(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.hasInitialized=!0}async identify(t,e){this.errorOnUninitialized(),this.userId=t,this.refreshInternalConfig(),await o(this.apiKey,"/users",{method:"POST",body:JSON.stringify({foreignId:this.userId,properties:e})}),await this.refreshUserFlowStates()}async group(t,e){this.errorOnUninitialized(),this.organizationId=t,this.refreshInternalConfig(),await o(this.apiKey,"/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.userId,foreignUserGroupId:this.organizationId,properties:e})}),await this.refreshUserFlowStates()}async track(t,e){this.errorOnUninitialized(),await o(this.apiKey,"/track",{method:"POST",body:JSON.stringify({foreignUserId:this.userId,foreignUserGroupId:this.organizationId,event:t,properties:e})})}async getFlow(t){return this.errorOnUninitialized(),this.flows.find(e=>e.id==t)}async getFlows(){return this.errorOnUninitialized(),this.flows}async reset(){E(),this.userId=I(),this.organizationId=void 0}errorOnUninitialized(){if(!this.hasInitialized)throw new Error("Frigade has not been initialized yet. Please call Frigade.init() before using any other methods.")}async refreshUserFlowStates(){let t=p(this.internalConfig);l[t]={refreshUserFlowStates:async()=>{},userFlowStates:{}},l[t].refreshUserFlowStates=async()=>{let e=await o(this.apiKey,`/userFlowStates?foreignUserId=${this.userId}${this.organizationId?`&foreignUserGroupId=${this.organizationId}`:""}`);e&&e.data&&e.data.forEach(r=>{l[t].userFlowStates[r.flowId]=r})},await l[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await o(this.apiKey,"/flows");t&&t.data&&t.data.forEach(a=>{this.flows.push(new w(this.internalConfig,a))})}refreshInternalConfig(){this.internalConfig={apiKey:this.apiKey,userId:this.userId,organizationId:this.organizationId}}},v=new F,b=v;var H=b;export{w as Flow,H as default};
2
+ var O="0.1.0";import R from"cross-fetch";import{v4 as _}from"uuid";var y="COMPLETED_FLOW";var T="STARTED_FLOW",E="NOT_STARTED_FLOW",p="COMPLETED_STEP",S="STARTED_STEP",U="frigade-last-call-at-",P="frigade-last-call-data-",D="frigade-guest-key",A="guest_";function L(i){return{config:{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json","X-Frigade-SDK-Version":O,"X-Frigade-SDK-Platform":"Javascript"}}}}function I(i){return window&&window.localStorage?window.localStorage.getItem(i):null}function C(i,t){window&&window.localStorage&&window.localStorage.setItem(i,t)}function b(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(i=>{i.startsWith("frigade-")&&window.localStorage.removeItem(i)})}async function v(i,t){let e=U+i,a=P+i;if(window&&window.localStorage&&t&&t.body&&t.method==="POST"){let r=I(e),g=I(a);if(r&&g&&g==t.body){let d=new Date(r);if(new Date().getTime()-d.getTime()<1e3)return u()}C(e,new Date().toISOString()),C(a,t.body)}let s;try{s=await R(i,t)}catch(r){return u(r)}return s?s.staus>=400?u(s.statusText):s.json():u()}function u(i){return i&&console.log("Call to Frigade failed",i),{json:()=>({})}}function F(){if(typeof window<"u"&&typeof window.localStorage<"u"){let i=I(D);return i||(i=`${A}${_()}`,window.localStorage.setItem(D,i)),i}}function o(i,t,e){return v(`//api.frigade.com/v1/public${t}`,{...e??{},...L(i).config})}var l={};function c(i){return`${i.__instanceId}-${i.apiKey}:${i.userId??""}:${i.organizationId??""}`}var f=class{constructor(t,e){this.internalConfig=t,this.flowDataRaw=e,this.initFromRawData(e)}initFromRawData(t){let e=JSON.parse(t.data),a=e.steps??e.data??[];this.id=t.slug,this.metadata=t,this.rawData=e,this.title=this.rawData.title,this.subtitle=this.rawData.subtitle;let s=this.getUserFlowState();this.isCompleted=s.flowState==y,this.isStarted=s.flowState==T,this.steps={},a.forEach((r,g)=>{let d=s.stepStates[r.id],n={...r,isCompleted:d.actionType==p,isStarted:d.actionType==S,isHidden:d.hidden,isBlocked:d.blocked,order:g};n.start=async h=>{n.isCompleted=!0,await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:r.id,data:h??{},createdAt:new Date().toISOString(),actionType:S})}),await this.refreshUserFlowState();let w=this.getUserFlowState();n.isCompleted=w.stepStates[r.id].actionType==p,n.isStarted=w.stepStates[r.id].actionType==S},n.complete=async h=>{n.isCompleted=!0,await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:r.id,data:h??{},createdAt:new Date().toISOString(),actionType:p})}),await this.refreshUserFlowState();let w=this.getUserFlowState();n.isCompleted=w.stepStates[r.id].actionType==p,n.isStarted=w.stepStates[r.id].actionType==S},this.steps[r.id]=n})}async start(t){let e=this.getCurrentStepIndex(),a=e!=-1?this.steps[e].id:"unknown";await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:a,data:t??{},createdAt:new Date().toISOString(),actionType:T})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){let e=this.getCurrentStepIndex(),a=e!=-1?this.getStepByIndex(e).id:"unknown";await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:a,data:t??{},createdAt:new Date().toISOString(),actionType:y})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){await o(this.internalConfig.apiKey,"/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.internalConfig.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:E})})}getStep(t){return this.steps[t]}getStepByIndex(t){return this.steps[Object.keys(this.steps)[t]]}getCurrentStepIndex(){var a;let t=this.getUserFlowState();if(!t)return 0;let e=t.lastStepId;return((a=this.steps[e])==null?void 0:a.order)??0}getUserFlowState(){return l[c(this.internalConfig)].userFlowStates[this.id]}async refreshUserFlowState(){await l[c(this.internalConfig)].refreshUserFlowStates()}};var m=class{constructor(t,e){this.userId=F();this.hasInitialized=!1;this.__instanceId="";this.flows=[];this.__instanceId=Math.random().toString(36).substring(7),this.init(t,e)}async init(t,e){this.apiKey=t,this.config=e,e!=null&&e.userId&&(this.userId=e.userId),e!=null&&e.organizationId&&(this.organizationId=e.organizationId),this.refreshInternalConfig(),await this.refreshUserFlowStates(),await this.refreshFlows(),this.hasInitialized=!0}async identify(t,e){await this.initIfNeeded(),this.userId=t,this.refreshInternalConfig(),await o(this.apiKey,"/users",{method:"POST",body:JSON.stringify({foreignId:this.userId,properties:e})}),await this.refreshUserFlowStates()}async group(t,e){await this.initIfNeeded(),this.organizationId=t,this.refreshInternalConfig(),await o(this.apiKey,"/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.userId,foreignUserGroupId:this.organizationId,properties:e})}),await this.refreshUserFlowStates()}async track(t,e){await this.initIfNeeded(),await o(this.apiKey,"/track",{method:"POST",body:JSON.stringify({foreignUserId:this.userId,foreignUserGroupId:this.organizationId,event:t,properties:e})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){b(),this.userId=F(),this.organizationId=void 0}async initIfNeeded(){this.hasInitialized||await this.init(this.apiKey,this.config)}async refreshUserFlowStates(){let t=c(this.internalConfig);l[t]={refreshUserFlowStates:async()=>{},userFlowStates:{}},l[t].refreshUserFlowStates=async()=>{let e=await o(this.apiKey,`/userFlowStates?foreignUserId=${this.userId}${this.organizationId?`&foreignUserGroupId=${this.organizationId}`:""}`);e&&e.data&&e.data.forEach(s=>{l[t].userFlowStates[s.flowId]=s})},await l[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await o(this.apiKey,"/flows");t&&t.data&&t.data.forEach(a=>{this.flows.push(new f(this.internalConfig,a))})}refreshInternalConfig(){this.internalConfig={apiKey:this.apiKey,userId:this.userId,organizationId:this.organizationId,__instanceId:this.__instanceId}}};export{f as Flow,m as Frigade};
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/core/flow.ts","../src/core/frigade.ts","../src/index.ts"],"sourcesContent":["export const VERSION_NUMBER = '0.0.6'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const ABORTED_FLOW = 'ABORTED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'ABORTED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\n\nfunction getConfig(apiKey: string) {\n return {\n config: {\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}\n\nfunction getLocalStorage(key: string) {\n if (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (window && window.localStorage && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (window && window.localStorage) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getConfig(apiKey).config,\n })\n}\n","import { InternalConfig, UserFlowState } from '../types'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: InternalConfig): string {\n return `${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.organizationId ?? ''\n }`\n}\n","import { InternalConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n COMPLETED_FLOW,\n COMPLETED_STEP,\n fetcher,\n NOT_STARTED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\n\nexport default class Flow {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `flow-data.yml` as a JSON decoded object\n */\n public rawData: Record<any, any>\n /**\n * The steps contained in the `data` array in `flow-data.yml`\n */\n public steps: FlowStep[]\n /**\n * The user-facing title of the flow, if defined at the top level of `flow-data.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `flow-data.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public metadata: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n\n private flowDataRaw: FlowDataRaw\n\n private internalConfig: InternalConfig\n\n constructor(internalConfig: InternalConfig, flowDataRaw: FlowDataRaw) {\n this.internalConfig = internalConfig\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.data\n this.id = flowDataRaw.slug\n this.metadata = flowDataRaw\n this.rawData = flowDataYml\n this.title = this.rawData.title\n this.subtitle = this.rawData.subtitle\n\n const userFlowState = this.getUserFlowState()\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.steps = [\n ...steps.map((step) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n stepObj.isCompleted = true\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: step.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n const updatedUserFlowState = this.getUserFlowState()\n stepObj.isCompleted =\n updatedUserFlowState.stepStates[step.id].actionType == COMPLETED_STEP\n stepObj.isStarted = updatedUserFlowState.stepStates[step.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n stepObj.isCompleted = true\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: step.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n const updatedUserFlowState = this.getUserFlowState()\n stepObj.isCompleted =\n updatedUserFlowState.stepStates[step.id].actionType == COMPLETED_STEP\n stepObj.isStarted = updatedUserFlowState.stepStates[step.id].actionType == STARTED_STEP\n }\n\n return stepObj\n }),\n ]\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n const currentStepIndex = this.getCurrentStepIndex()\n const currentStepId = currentStepIndex != -1 ? this.steps[currentStepIndex].id : 'unknown'\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: currentStepId,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n const currentStepIndex = this.getCurrentStepIndex()\n const currentStepId = currentStepIndex != -1 ? this.steps[currentStepIndex].id : 'unknown'\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: currentStepId,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n }\n\n /**\n * Get a step by id\n */\n public getStep(id: string): FlowStep | undefined {\n return this.steps.find((step) => step.id == id)\n }\n\n /**\n * Function that gets current step index\n */\n public getCurrentStepIndex(): number {\n // Find the userFlowState with most recent timestamp\n const userFlowState = this.getUserFlowState()\n if (!userFlowState) {\n return 0\n }\n const currentStepId = userFlowState.lastStepId\n const index = this.steps.findIndex((step) => step.id === currentStepId)\n return index == -1 ? 0 : index\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = frigadeGlobalState[getGlobalStateKey(this.internalConfig)].userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await frigadeGlobalState[getGlobalStateKey(this.internalConfig)].refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, InternalConfig, UserFlowState } from '../types'\nimport { fetcher, generateGuestId, resetAllLocalStorage } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\n\nexport class Frigade {\n private apiKey?: string\n private userId: string = generateGuestId()\n private organizationId?: string\n private config?: FrigadeConfig\n private hasInitialized = false\n private internalConfig?: InternalConfig\n\n private flows: Flow[] = []\n\n public async init(apiKey: string, config?: FrigadeConfig): Promise<void> {\n this.apiKey = apiKey\n this.config = config\n if (config?.userId) {\n this.userId = config.userId\n }\n if (config?.organizationId) {\n this.organizationId = config.organizationId\n }\n this.refreshInternalConfig()\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n this.hasInitialized = true\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n this.errorOnUninitialized()\n this.userId = userId\n this.refreshInternalConfig()\n await fetcher(this.apiKey, '/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n this.errorOnUninitialized()\n this.organizationId = organizationId\n this.refreshInternalConfig()\n await fetcher(this.apiKey, '/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.userId,\n foreignUserGroupId: this.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n this.errorOnUninitialized()\n await fetcher(this.apiKey, '/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.userId,\n foreignUserGroupId: this.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n this.errorOnUninitialized()\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n this.errorOnUninitialized()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.userId = generateGuestId()\n this.organizationId = undefined\n }\n\n private errorOnUninitialized() {\n if (!this.hasInitialized) {\n throw new Error(\n 'Frigade has not been initialized yet. Please call Frigade.init() before using any other methods.'\n )\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.internalConfig)\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: {},\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await fetcher(\n this.apiKey,\n `/userFlowStates?foreignUserId=${this.userId}${\n this.organizationId ? `&foreignUserGroupId=${this.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await fetcher(this.apiKey, '/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.internalConfig, flowData))\n })\n }\n }\n\n private refreshInternalConfig() {\n this.internalConfig = {\n apiKey: this.apiKey,\n userId: this.userId,\n organizationId: this.organizationId,\n }\n }\n}\n\nconst frigade = new Frigade()\nexport default frigade\n","import frigade from './core/frigade'\nimport Flow from './core/flow'\n\nexport { Flow }\n\nexport default frigade\n"],"mappings":"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","names":["VERSION_NUMBER","fetch","uuidv4","COMPLETED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","getConfig","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","fetcher","path","frigadeGlobalState","getGlobalStateKey","internalConfig","Flow","internalConfig","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","step","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","fetcher","updatedUserFlowState","currentStepIndex","currentStepId","NOT_STARTED_FLOW","id","index","frigadeGlobalState","getGlobalStateKey","Frigade","generateGuestId","apiKey","config","userId","properties","fetcher","organizationId","event","flowId","flow","resetAllLocalStorage","globalStateKey","getGlobalStateKey","frigadeGlobalState","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","frigade","frigade_default","src_default","frigade_default"]}
1
+ {"version":3,"sources":["../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export const VERSION_NUMBER = '0.1.0'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const ABORTED_FLOW = 'ABORTED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'ABORTED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\n\nfunction getConfig(apiKey: string) {\n return {\n config: {\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}\n\nfunction getLocalStorage(key: string) {\n if (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (window && window.localStorage && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getConfig(apiKey).config,\n })\n}\n","import { InternalConfig, UserFlowState } from '../types'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: InternalConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.organizationId ?? ''\n }`\n}\n","import { InternalConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n COMPLETED_FLOW,\n COMPLETED_STEP,\n fetcher,\n NOT_STARTED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\n\nexport default class Flow {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public rawData: Record<any, any>\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Record<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public metadata: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n\n private flowDataRaw: FlowDataRaw\n\n private internalConfig: InternalConfig\n\n constructor(internalConfig: InternalConfig, flowDataRaw: FlowDataRaw) {\n this.internalConfig = internalConfig\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.metadata = flowDataRaw\n this.rawData = flowDataYml\n this.title = this.rawData.title\n this.subtitle = this.rawData.subtitle\n\n const userFlowState = this.getUserFlowState()\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.steps = {}\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n stepObj.isCompleted = true\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: step.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n const updatedUserFlowState = this.getUserFlowState()\n stepObj.isCompleted = updatedUserFlowState.stepStates[step.id].actionType == COMPLETED_STEP\n stepObj.isStarted = updatedUserFlowState.stepStates[step.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n stepObj.isCompleted = true\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: step.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n await this.refreshUserFlowState()\n const updatedUserFlowState = this.getUserFlowState()\n stepObj.isCompleted = updatedUserFlowState.stepStates[step.id].actionType == COMPLETED_STEP\n stepObj.isStarted = updatedUserFlowState.stepStates[step.id].actionType == STARTED_STEP\n }\n\n this.steps[step.id] = stepObj\n })\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n const currentStepIndex = this.getCurrentStepIndex()\n const currentStepId = currentStepIndex != -1 ? this.steps[currentStepIndex].id : 'unknown'\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: currentStepId,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n const currentStepIndex = this.getCurrentStepIndex()\n const currentStepId =\n currentStepIndex != -1 ? this.getStepByIndex(currentStepIndex).id : 'unknown'\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: currentStepId,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n await fetcher(this.internalConfig.apiKey, `/flowResponses`, {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.internalConfig.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n }\n\n /**\n * Get a step by id\n */\n public getStep(id: string): FlowStep | undefined {\n return this.steps[id]\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps[Object.keys(this.steps)[index]]\n }\n\n /**\n * Function that gets current step index\n */\n public getCurrentStepIndex(): number {\n // Find the userFlowState with most recent timestamp\n const userFlowState = this.getUserFlowState()\n if (!userFlowState) {\n return 0\n }\n const currentStepId = userFlowState.lastStepId\n return this.steps[currentStepId]?.order ?? 0\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = frigadeGlobalState[getGlobalStateKey(this.internalConfig)].userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await frigadeGlobalState[getGlobalStateKey(this.internalConfig)].refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, InternalConfig, UserFlowState } from '../types'\nimport { fetcher, generateGuestId, resetAllLocalStorage } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\n\nexport class Frigade {\n private apiKey?: string\n private userId: string = generateGuestId()\n private organizationId?: string\n private config?: FrigadeConfig\n private hasInitialized = false\n private internalConfig?: InternalConfig\n private __instanceId = ''\n\n private flows: Flow[] = []\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n this.__instanceId = Math.random().toString(36).substring(7)\n this.init(apiKey, config)\n }\n\n private async init(apiKey: string, config?: FrigadeConfig): Promise<void> {\n this.apiKey = apiKey\n this.config = config\n if (config?.userId) {\n this.userId = config.userId\n }\n if (config?.organizationId) {\n this.organizationId = config.organizationId\n }\n this.refreshInternalConfig()\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n this.hasInitialized = true\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.userId = userId\n this.refreshInternalConfig()\n await fetcher(this.apiKey, '/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.organizationId = organizationId\n this.refreshInternalConfig()\n await fetcher(this.apiKey, '/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.userId,\n foreignUserGroupId: this.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await fetcher(this.apiKey, '/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.userId,\n foreignUserGroupId: this.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.userId = generateGuestId()\n this.organizationId = undefined\n }\n\n private async initIfNeeded() {\n if (!this.hasInitialized) {\n await this.init(this.apiKey, this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.internalConfig)\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: {},\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await fetcher(\n this.apiKey,\n `/userFlowStates?foreignUserId=${this.userId}${\n this.organizationId ? `&foreignUserGroupId=${this.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await fetcher(this.apiKey, '/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.internalConfig, flowData))\n })\n }\n }\n\n private refreshInternalConfig() {\n this.internalConfig = {\n apiKey: this.apiKey,\n userId: this.userId,\n organizationId: this.organizationId,\n __instanceId: this.__instanceId,\n }\n }\n}\n"],"mappings":";AAAO,IAAMA,EAAiB,QCC9B,OAAOC,MAAW,cAClB,OAAS,MAAMC,MAAc,OAGtB,IAAMC,EAAiB,iBAEvB,IAAMC,EAAe,eACfC,EAAmB,mBACnBC,EAAiB,iBACjBC,EAAe,eAGtBC,EAAoB,wBACpBC,EAAsB,0BACtBC,EAAY,oBACZC,EAAe,SAErB,SAASC,EAAUC,EAAgB,CACjC,MAAO,CACL,OAAQ,CACN,QAAS,CACP,cAAe,UAAUA,IACzB,eAAgB,mBAChB,wBAAyBC,EACzB,yBAA0B,YAC5B,CACF,CACF,CACF,CAEA,SAASC,EAAgBC,EAAa,CACpC,OAAI,QAAU,OAAO,aACZ,OAAO,aAAa,QAAQA,CAAG,EAEjC,IACT,CAEA,SAASC,EAAgBD,EAAaE,EAAe,CAC/C,QAAU,OAAO,cACnB,OAAO,aAAa,QAAQF,EAAKE,CAAK,CAE1C,CAEO,SAASC,GAAuB,CACjC,QAAU,OAAO,cAEnB,OAAO,KAAK,OAAO,YAAY,EAAE,QAASH,GAAQ,CAC5CA,EAAI,WAAW,UAAU,GAC3B,OAAO,aAAa,WAAWA,CAAG,CAEtC,CAAC,CAEL,CAEA,eAAsBI,EAAcC,EAAaC,EAAc,CAC7D,IAAMC,EAAgBf,EAAoBa,EACpCG,EAAkBf,EAAsBY,EAC9C,GAAI,QAAU,OAAO,cAAgBC,GAAWA,EAAQ,MAAQA,EAAQ,SAAW,OAAQ,CACzF,IAAMG,EAAWV,EAAgBQ,CAAa,EACxCG,EAAeX,EAAgBS,CAAe,EACpD,GAAIC,GAAYC,GAAgBA,GAAgBJ,EAAQ,KAAM,CAC5D,IAAMK,EAAe,IAAI,KAAKF,CAAQ,EAItC,GAHY,IAAI,KAAK,EACJ,QAAQ,EAAIE,EAAa,QAAQ,EAEvC,IACT,OAAOC,EAAiB,EAG5BX,EAAgBM,EAAe,IAAI,KAAK,EAAE,YAAY,CAAC,EACvDN,EAAgBO,EAAiBF,EAAQ,IAAI,EAG/C,IAAIO,EACJ,GAAI,CACFA,EAAW,MAAMC,EAAMT,EAAKC,CAAO,CACrC,OAASS,EAAP,CACA,OAAOH,EAAiBG,CAAK,CAC/B,CAEA,OAAKF,EAIDA,EAAS,OAAS,IACbD,EAAiBC,EAAS,UAAU,EAGtCA,EAAS,KAAK,EAPZD,EAAiB,CAQ5B,CAEA,SAASA,EAAiBG,EAAa,CACrC,OAAIA,GACF,QAAQ,IAAI,yBAA0BA,CAAK,EAItC,CACL,KAAM,KAAO,CAAC,EAChB,CACF,CAEO,SAASC,GAAkB,CAChC,GAAI,OAAO,OAAW,KAAe,OAAO,OAAO,aAAiB,IAAa,CAC/E,IAAIC,EAAUlB,EAAgBL,CAAS,EACvC,OAAKuB,IACHA,EAAU,GAAGtB,IAAeuB,EAAO,IACnC,OAAO,aAAa,QAAQxB,EAAWuB,CAAO,GAEzCA,EAEX,CAEO,SAASE,EAAQtB,EAAgBuB,EAAcd,EAA4B,CAChF,OAAOF,EAAc,8BAA8BgB,IAAQ,CACzD,GAAId,GAAW,CAAC,EAChB,GAAGV,EAAUC,CAAM,EAAE,MACvB,CAAC,CACH,CChHO,IAAIwB,EAAyD,CAAC,EAE9D,SAASC,EAAkBC,EAAwC,CACxE,MAAO,GAAGA,EAAe,gBAAgBA,EAAe,UAAUA,EAAe,QAAU,MACzFA,EAAe,gBAAkB,IAErC,CCAA,IAAqBC,EAArB,KAA0B,CAsCxB,YAAYC,EAAgCC,EAA0B,CACpE,KAAK,eAAiBD,EACtB,KAAK,YAAcC,EACnB,KAAK,gBAAgBA,CAAW,CAClC,CAEQ,gBAAgBA,EAA0B,CAChD,IAAMC,EAAc,KAAK,MAAMD,EAAY,IAAI,EACzCE,EAAQD,EAAY,OAASA,EAAY,MAAQ,CAAC,EACxD,KAAK,GAAKD,EAAY,KACtB,KAAK,SAAWA,EAChB,KAAK,QAAUC,EACf,KAAK,MAAQ,KAAK,QAAQ,MAC1B,KAAK,SAAW,KAAK,QAAQ,SAE7B,IAAME,EAAgB,KAAK,iBAAiB,EAE5C,KAAK,YAAcA,EAAc,WAAaC,EAC9C,KAAK,UAAYD,EAAc,WAAaE,EAC5C,KAAK,MAAQ,CAAC,EAEdH,EAAM,QAAQ,CAACI,EAAMC,IAAU,CAC7B,IAAMC,EAAoBL,EAAc,WAAWG,EAAK,EAAE,EACpDG,EAAU,CACd,GAAGH,EACH,YAAaE,EAAkB,YAAcE,EAC7C,UAAWF,EAAkB,YAAcG,EAC3C,SAAUH,EAAkB,OAC5B,UAAWA,EAAkB,QAC7B,MAAOD,CACT,EAEAE,EAAQ,MAAQ,MAAOG,GAA8C,CACnEH,EAAQ,YAAc,GACtB,MAAMI,EAAQ,KAAK,eAAe,OAAQ,iBAAkB,CAC1D,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,eAAe,OACnC,SAAU,KAAK,GACf,OAAQP,EAAK,GACb,KAAMM,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYD,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,IAAMG,EAAuB,KAAK,iBAAiB,EACnDL,EAAQ,YAAcK,EAAqB,WAAWR,EAAK,EAAE,EAAE,YAAcI,EAC7ED,EAAQ,UAAYK,EAAqB,WAAWR,EAAK,EAAE,EAAE,YAAcK,CAC7E,EAEAF,EAAQ,SAAW,MAAOG,GAA8C,CACtEH,EAAQ,YAAc,GACtB,MAAMI,EAAQ,KAAK,eAAe,OAAQ,iBAAkB,CAC1D,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,eAAe,OACnC,SAAU,KAAK,GACf,OAAQP,EAAK,GACb,KAAMM,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYF,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,IAAMI,EAAuB,KAAK,iBAAiB,EACnDL,EAAQ,YAAcK,EAAqB,WAAWR,EAAK,EAAE,EAAE,YAAcI,EAC7ED,EAAQ,UAAYK,EAAqB,WAAWR,EAAK,EAAE,EAAE,YAAcK,CAC7E,EAEA,KAAK,MAAML,EAAK,EAAE,EAAIG,CACxB,CAAC,CACH,CAKA,MAAa,MAAMG,EAA2C,CAC5D,IAAMG,EAAmB,KAAK,oBAAoB,EAC5CC,EAAgBD,GAAoB,GAAK,KAAK,MAAMA,CAAgB,EAAE,GAAK,UACjF,MAAMF,EAAQ,KAAK,eAAe,OAAQ,iBAAkB,CAC1D,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,eAAe,OACnC,SAAU,KAAK,GACf,OAAQG,EACR,KAAMJ,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYP,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,CACvC,CAKA,MAAa,SAASO,EAA2C,CAC/D,IAAMG,EAAmB,KAAK,oBAAoB,EAC5CC,EACJD,GAAoB,GAAK,KAAK,eAAeA,CAAgB,EAAE,GAAK,UACtE,MAAMF,EAAQ,KAAK,eAAe,OAAQ,iBAAkB,CAC1D,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,eAAe,OACnC,SAAU,KAAK,GACf,OAAQG,EACR,KAAMJ,GAAc,CAAC,EACrB,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYR,CACd,CAAC,CACH,CAAC,EACD,MAAM,KAAK,qBAAqB,EAChC,KAAK,gBAAgB,KAAK,WAAW,CACvC,CAKA,MAAa,SAAU,CACrB,MAAMS,EAAQ,KAAK,eAAe,OAAQ,iBAAkB,CAC1D,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,eAAe,OACnC,SAAU,KAAK,GACf,OAAQ,UACR,KAAM,CAAC,EACP,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAYI,CACd,CAAC,CACH,CAAC,CACH,CAKO,QAAQC,EAAkC,CAC/C,OAAO,KAAK,MAAMA,CAAE,CACtB,CAMO,eAAeX,EAAqC,CACzD,OAAO,KAAK,MAAM,OAAO,KAAK,KAAK,KAAK,EAAEA,CAAK,CAAC,CAClD,CAKO,qBAA8B,CA3MvC,IAAAY,EA6MI,IAAMhB,EAAgB,KAAK,iBAAiB,EAC5C,GAAI,CAACA,EACH,MAAO,GAET,IAAMa,EAAgBb,EAAc,WACpC,QAAOgB,EAAA,KAAK,MAAMH,CAAa,IAAxB,YAAAG,EAA2B,QAAS,CAC7C,CAEQ,kBAAkC,CAExC,OADuBC,EAAmBC,EAAkB,KAAK,cAAc,CAAC,EAAE,eAC5D,KAAK,EAAE,CAC/B,CAEA,MAAc,sBAAuB,CACnC,MAAMD,EAAmBC,EAAkB,KAAK,cAAc,CAAC,EAAE,sBAAsB,CACzF,CACF,ECvNO,IAAMC,EAAN,KAAc,CAWnB,YAAYC,EAAgBC,EAAwB,CATpD,KAAQ,OAAiBC,EAAgB,EAGzC,KAAQ,eAAiB,GAEzB,KAAQ,aAAe,GAEvB,KAAQ,MAAgB,CAAC,EAGvB,KAAK,aAAe,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,EAC1D,KAAK,KAAKF,EAAQC,CAAM,CAC1B,CAEA,MAAc,KAAKD,EAAgBC,EAAuC,CACxE,KAAK,OAASD,EACd,KAAK,OAASC,EACVA,GAAA,MAAAA,EAAQ,SACV,KAAK,OAASA,EAAO,QAEnBA,GAAA,MAAAA,EAAQ,iBACV,KAAK,eAAiBA,EAAO,gBAE/B,KAAK,sBAAsB,EAC3B,MAAM,KAAK,sBAAsB,EACjC,MAAM,KAAK,aAAa,EACxB,KAAK,eAAiB,EACxB,CAEA,MAAa,SAASE,EAAgBC,EAAiD,CACrF,MAAM,KAAK,aAAa,EACxB,KAAK,OAASD,EACd,KAAK,sBAAsB,EAC3B,MAAME,EAAQ,KAAK,OAAQ,SAAU,CACnC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,UAAW,KAAK,OAChB,WAAAD,CACF,CAAC,CACH,CAAC,EACD,MAAM,KAAK,sBAAsB,CACnC,CAEA,MAAa,MAAME,EAAwBF,EAAiD,CAC1F,MAAM,KAAK,aAAa,EACxB,KAAK,eAAiBE,EACtB,KAAK,sBAAsB,EAC3B,MAAMD,EAAQ,KAAK,OAAQ,cAAe,CACxC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OACpB,mBAAoB,KAAK,eACzB,WAAAD,CACF,CAAC,CACH,CAAC,EACD,MAAM,KAAK,sBAAsB,CACnC,CAEA,MAAa,MAAMG,EAAeH,EAAiD,CACjF,MAAM,KAAK,aAAa,EACxB,MAAMC,EAAQ,KAAK,OAAQ,SAAU,CACnC,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,cAAe,KAAK,OACpB,mBAAoB,KAAK,eACzB,MAAAE,EACA,WAAAH,CACF,CAAC,CACH,CAAC,CACH,CAEA,MAAa,QAAQI,EAAgB,CACnC,aAAM,KAAK,aAAa,EACjB,KAAK,MAAM,KAAMC,GAASA,EAAK,IAAMD,CAAM,CACpD,CAEA,MAAa,UAAW,CACtB,aAAM,KAAK,aAAa,EACjB,KAAK,KACd,CAEA,MAAa,OAAQ,CACnBE,EAAqB,EACrB,KAAK,OAASR,EAAgB,EAC9B,KAAK,eAAiB,MACxB,CAEA,MAAc,cAAe,CACtB,KAAK,gBACR,MAAM,KAAK,KAAK,KAAK,OAAQ,KAAK,MAAM,CAE5C,CAEA,MAAc,uBAAuC,CACnD,IAAMS,EAAiBC,EAAkB,KAAK,cAAc,EAC5DC,EAAmBF,CAAc,EAAI,CACnC,sBAAuB,SAAY,CAAC,EACpC,eAAgB,CAAC,CACnB,EACAE,EAAmBF,CAAc,EAAE,sBAAwB,SAAY,CACrE,IAAMG,EAAoB,MAAMT,EAC9B,KAAK,OACL,iCAAiC,KAAK,SACpC,KAAK,eAAiB,uBAAuB,KAAK,iBAAmB,IAEzE,EACIS,GAAqBA,EAAkB,MACpBA,EAAkB,KACxB,QAASC,GAAkB,CACxCF,EAAmBF,CAAc,EAAE,eAAeI,EAAc,MAAM,EAAIA,CAC5E,CAAC,CAEL,EACA,MAAMF,EAAmBF,CAAc,EAAE,sBAAsB,CACjE,CAEA,MAAc,cAAe,CAC3B,KAAK,MAAQ,CAAC,EACd,IAAMK,EAAc,MAAMX,EAAQ,KAAK,OAAQ,QAAQ,EACnDW,GAAeA,EAAY,MACbA,EAAY,KAClB,QAASC,GAAa,CAC9B,KAAK,MAAM,KAAK,IAAIC,EAAK,KAAK,eAAgBD,CAAQ,CAAC,CACzD,CAAC,CAEL,CAEQ,uBAAwB,CAC9B,KAAK,eAAiB,CACpB,OAAQ,KAAK,OACb,OAAQ,KAAK,OACb,eAAgB,KAAK,eACrB,aAAc,KAAK,YACrB,CACF,CACF","names":["VERSION_NUMBER","fetch","uuidv4","COMPLETED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","getConfig","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","fetcher","path","frigadeGlobalState","getGlobalStateKey","internalConfig","Flow","internalConfig","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","fetcher","updatedUserFlowState","currentStepIndex","currentStepId","NOT_STARTED_FLOW","id","_a","frigadeGlobalState","getGlobalStateKey","Frigade","apiKey","config","generateGuestId","userId","properties","fetcher","organizationId","event","flowId","flow","resetAllLocalStorage","globalStateKey","getGlobalStateKey","frigadeGlobalState","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frigade/js",
3
- "version": "0.0.6",
3
+ "version": "0.1.0",
4
4
  "description": "The official Javascript SDK for Frigade.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -63,9 +63,9 @@
63
63
  "author": "Frigade Inc.",
64
64
  "license": "MIT",
65
65
  "bugs": {
66
- "url": "https://github.com/FrigadeHQ/frigade-js/issues"
66
+ "url": "https://github.com/FrigadeHQ/javascript/issues"
67
67
  },
68
- "homepage": "https://github.com/FrigadeHQ/frigade-js#readme",
68
+ "homepage": "https://github.com/FrigadeHQ/javascript/tree/main/packages/js-api#readme",
69
69
  "dependencies": {
70
70
  "cross-fetch": "^4.0.0",
71
71
  "uuid": "^9.0.0"