@frigade/js 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +34 -26
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -13
- package/dist/index.mjs +0 -3
- package/dist/index.mjs.map +0 -1
package/README.md
CHANGED
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var J=Object.create;var m=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var M=Object.getPrototypeOf,$=Object.prototype.hasOwnProperty;var H=(e,s)=>{for(var t in s)m(e,t,{get:s[t],enumerable:!0})},P=(e,s,t,i)=>{if(s&&typeof s=="object"||typeof s=="function")for(let a of K(s))!$.call(e,a)&&a!==t&&m(e,a,{get:()=>s[a],enumerable:!(i=W(s,a))||i.enumerable});return e};var z=(e,s,t)=>(t=e!=null?J(M(e)):{},P(s||!e||!e.__esModule?m(t,"default",{value:e,enumerable:!0}):t,e)),k=e=>P(m({},"__esModule",{value:!0}),e);var X={};H(X,{Flow:()=>w,Frigade:()=>b});module.exports=k(X);var C="0.1.2";var A=z(require("cross-fetch"),1),L=require("uuid");var T="COMPLETED_FLOW",R="SKIPPED_FLOW",I="STARTED_FLOW",N="NOT_STARTED_FLOW",g="COMPLETED_STEP",h="STARTED_STEP",j="frigade-last-call-at-",B="frigade-last-call-data-",U="frigade-guest-key",V="guest_";function x(e){return{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json","X-Frigade-SDK-Version":C,"X-Frigade-SDK-Platform":"Javascript"}}}function E(e){return window&&window.localStorage?window.localStorage.getItem(e):null}function _(e,s){window&&window.localStorage&&window.localStorage.setItem(e,s)}function v(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(e=>{e.startsWith("frigade-")&&window.localStorage.removeItem(e)})}async function G(e,s){let t=j+e,i=B+e;if(window&&window.localStorage&&s&&s.body&&s.method==="POST"){let o=E(t),l=E(i);if(o&&l&&l==s.body){let f=new Date(o);if(new Date().getTime()-f.getTime()<1e3)return y()}_(t,new Date().toISOString()),_(i,s.body)}let a;try{a=await(0,A.default)(e,s)}catch(o){return y(o)}return a?a.staus>=400?y(a.statusText):a.json():y()}function y(e){return e&&console.log("Call to Frigade failed",e),{json:()=>({})}}function O(){if(typeof window<"u"&&typeof window.localStorage<"u"){let e=E(U);return e||(e=`${V}${(0,L.v4)()}`,window.localStorage.setItem(U,e)),e}}var n={};function d(e){return`${e.__instanceId}-${e.apiKey}:${e.userId??""}:${e.organizationId??""}`}var p=class{constructor(s){this.config={apiKey:"",apiUrl:"//api.frigade.com/v1/public",userId:O(),__instanceId:Math.random().toString(36).substring(7)};this.config={...this.config,...s}}async fetch(s,t){return G(`${this.config.apiUrl}${s}`,{...t??{},...x(this.config.apiKey)})}};var w=class extends p{constructor(t,i){super(t);this.flowDataRaw=i,this.initFromRawData(i)}initFromRawData(t){let i=JSON.parse(t.data),a=i.steps??i.data??[];this.id=t.slug,this.metadata=t,this.rawData=i,this.title=this.rawData.title,this.subtitle=this.rawData.subtitle;let o=this.getUserFlowState();this.isCompleted=o.flowState==T,this.isStarted=o.flowState==I,this.isSkipped=o.flowState==R,this.steps=new Map,a.forEach((l,f)=>{let c=o.stepStates[l.id],S={...l,isCompleted:c.actionType==g,isStarted:c.actionType==h,isHidden:c.hidden,isBlocked:c.blocked,order:f};S.start=async D=>{let r=this.steps.get(l.id);if(r.isStarted||r.isCompleted)return;r.isStarted=!0;let u={...n[d(this.config)].userFlowStates[this.id]};u.stepStates[r.id].actionType=h,n[d(this.config)].userFlowStates[this.id]=u,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:r.id,data:D??{},createdAt:new Date().toISOString(),actionType:h})}),await this.refreshUserFlowState();let F=this.getUserFlowState();r.isCompleted=F.stepStates[r.id].actionType==g,r.isStarted=F.stepStates[r.id].actionType==h},S.complete=async D=>{let r=this.steps.get(l.id);if(r.isCompleted)return;r.isCompleted=!0;let u={...n[d(this.config)].userFlowStates[this.id]};u.stepStates[r.id].actionType=g,n[d(this.config)].userFlowStates[this.id]=u,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:r.id,data:D??{},createdAt:new Date().toISOString(),actionType:g})}),await this.refreshUserFlowState();let F=this.getUserFlowState();r.isCompleted=F.stepStates[r.id].actionType==g,r.isStarted=F.stepStates[r.id].actionType==h},this.steps.set(l.id,S)})}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let i={...n[d(this.config)].userFlowStates[this.id]};i.flowState=I,n[d(this.config)].userFlowStates[this.id]=i,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:I})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){if(this.isCompleted)return;this.isCompleted=!0;let i={...n[d(this.config)].userFlowStates[this.id]};i.flowState=T,n[d(this.config)].userFlowStates[this.id]=i,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:T})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:R})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,n[d(this.config)].userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:N})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let t=this.getUserFlowState(),a=Array.from(this.steps.keys()).find(o=>this.steps.get(o).isCompleted===!1)??Array.from(this.steps.keys())[0];return this.steps.get(a)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getUserFlowState(){return n[d(this.config)].userFlowStates[this.id]}async refreshUserFlowState(){await n[d(this.config)].refreshUserFlowStates()}};var b=class extends p{constructor(t,i){super({apiKey:t,...i});this.flows=[];this.onFlowStateChangeHandlers=[];this.init(this.config)}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,i){await this.initIfNeeded(),this.config.userId=t,await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:i})}),await this.refreshUserFlowStates()}async group(t,i){await this.initIfNeeded(),this.config.organizationId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,properties:i})}),await this.refreshUserFlowStates()}async track(t,i){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,event:t,properties:i})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(i=>i.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){v(),this.config.userId=O(),this.config.organizationId=void 0}onFlowStateChange(t){this.onFlowStateChangeHandlers.push(t)}removeOnFlowStateChangeHandler(t){this.onFlowStateChangeHandlers=this.onFlowStateChangeHandlers.filter(i=>i!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=d(this.config);if(!n[t]){let i=this,a={set:function(o,l,f){var c,S;return(o[l]&&((c=o[l])!=null&&c.flowState)&&JSON.stringify(o[l].flowState)!==JSON.stringify(f.flowState)||JSON.stringify((S=o[l])==null?void 0:S.stepStates)!==JSON.stringify(f.stepStates)||JSON.stringify(o[l].shouldTrigger)!==JSON.stringify(f.shouldTrigger))&&i.triggerEventHandlers(o[l],f),o[l]=f,!0}};n[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},a)},n[t].refreshUserFlowStates=async()=>{let o=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.organizationId?`&foreignUserGroupId=${this.config.organizationId}`:""}`);o&&o.data&&o.data.forEach(f=>{n[t].userFlowStates[f.flowId]=f})}}await n[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(a=>{this.flows.push(new w(this.config,a))})}triggerEventHandlers(t,i){t&&t.flowState!==i.flowState&&this.flows.forEach(a=>{a.id==i.flowId&&this.onFlowStateChangeHandlers.forEach(o=>{o(a,i.flowState,t==null?void 0:t.flowState)})})}};0&&(module.exports={Flow,Frigade});
|
|
3
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/Fetchable.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export { Frigade } from './core/frigade'\nimport Flow from './core/flow'\n\nexport { Flow }\n","export const VERSION_NUMBER = '0.1.2'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (window && window.localStorage && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.organizationId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: '//api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n this.config = {\n ...this.config,\n ...config,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport default class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public rawData: Record<any, any>\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public metadata: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n /**\n * Whether the flow has been skipped or not\n */\n public isSkipped: boolean\n\n private flowDataRaw: FlowDataRaw\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.metadata = flowDataRaw\n this.rawData = flowDataYml\n this.title = this.rawData.title\n this.subtitle = this.rawData.subtitle\n\n const userFlowState = this.getUserFlowState()\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.isSkipped = userFlowState.flowState == SKIPPED_FLOW\n this.steps = new Map()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const clone = {\n ...frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id],\n }\n clone.stepStates[currentStep.id].actionType = STARTED_STEP\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = clone\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n currentStep.isCompleted = true\n const clone = {\n ...frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id],\n }\n clone.stepStates[currentStep.id].actionType = COMPLETED_STEP\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = clone\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n this.steps.set(step.id, stepObj)\n })\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const clone = { ...frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] }\n clone.flowState = STARTED_FLOW\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = clone\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n\n this.isCompleted = true\n const clone = { ...frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] }\n clone.flowState = COMPLETED_FLOW\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = clone\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n // Find the userFlowState with most recent timestamp\n const userFlowState = this.getUserFlowState()\n\n // TEMP: lastStepId appears to be the last step that a flowState event was recorded for?\n // const lastStepId =\n // userFlowState?.lastStepId?.length > 0 && userFlowState?.lastStepId !== 'unknown'\n // ? userFlowState?.lastStepId\n // : undefined\n\n // TEMP: Return the lowest-ordered incomplete step in the flow\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await frigadeGlobalState[getGlobalStateKey(this.config)].refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { generateGuestId, resetAllLocalStorage, UserFlowStatus } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n private onFlowStateChangeHandlers: ((\n flow: Flow,\n newState: UserFlowStatus,\n previousState: UserFlowStatus\n ) => void)[] = []\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.userId = userId\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.organizationId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.config.userId = generateGuestId()\n this.config.organizationId = undefined\n }\n\n public onFlowStateChange(\n handler: (flow: Flow, newState: UserFlowStatus, previousState: UserFlowStatus) => void\n ) {\n this.onFlowStateChangeHandlers.push(handler)\n }\n\n public removeOnFlowStateChangeHandler(\n handler: (flow: Flow, newState: UserFlowStatus, previousState: UserFlowStatus) => void\n ) {\n this.onFlowStateChangeHandlers = this.onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n (target[key] &&\n target[key]?.flowState &&\n JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState)) ||\n JSON.stringify(target[key]?.stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger)\n ) {\n that.triggerEventHandlers(target[key], value)\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.organizationId ? `&foreignUserGroupId=${this.config.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n })\n }\n }\n\n private triggerEventHandlers(\n previousUserFlowState: UserFlowState,\n newUserFlowState: UserFlowState\n ) {\n if (previousUserFlowState && previousUserFlowState.flowState !== newUserFlowState.flowState) {\n this.flows.forEach((flow) => {\n if (flow.id == newUserFlowState.flowId) {\n this.onFlowStateChangeHandlers.forEach((handler) => {\n handler(flow, newUserFlowState.flowState, previousUserFlowState?.flowState)\n })\n }\n })\n }\n }\n}\n"],"mappings":"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","names":["src_exports","__export","Flow","Frigade","__toCommonJS","VERSION_NUMBER","import_cross_fetch","import_uuid","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","path","options","gracefulFetch","getHeaders","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","clone","frigadeGlobalState","getGlobalStateKey","updatedUserFlowState","NOT_STARTED_FLOW","currentStepId","key","Frigade","Fetchable","apiKey","config","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","generateGuestId","handler","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","_a","_b","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","previousUserFlowState","newUserFlowState"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
interface FrigadeConfig {
|
|
2
|
+
apiKey?: string;
|
|
2
3
|
/**
|
|
3
4
|
* API url to use for all requests. Defaults to https://api.frigade.com
|
|
4
5
|
*/
|
|
@@ -11,14 +12,11 @@ interface FrigadeConfig {
|
|
|
11
12
|
* Organization ID to use for all requests. Defaults to null.
|
|
12
13
|
*/
|
|
13
14
|
organizationId?: string;
|
|
14
|
-
}
|
|
15
|
-
interface InternalConfig {
|
|
16
|
-
apiKey: string;
|
|
17
|
-
userId?: string;
|
|
18
|
-
organizationId?: string;
|
|
19
15
|
__instanceId?: string;
|
|
20
16
|
}
|
|
21
17
|
|
|
18
|
+
type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW';
|
|
19
|
+
|
|
22
20
|
interface FlowDataRaw {
|
|
23
21
|
id: number;
|
|
24
22
|
name: string;
|
|
@@ -159,14 +157,20 @@ interface FlowStep {
|
|
|
159
157
|
/**
|
|
160
158
|
* Function that marks the step started
|
|
161
159
|
*/
|
|
162
|
-
start: (properties?: Record<string | number, any>) => void
|
|
160
|
+
start: (properties?: Record<string | number, any>) => Promise<void>;
|
|
163
161
|
/**
|
|
164
162
|
* Function that marks the step completed
|
|
165
163
|
*/
|
|
166
|
-
complete: (properties?: Record<string | number, any>) => void
|
|
164
|
+
complete: (properties?: Record<string | number, any>) => Promise<void>;
|
|
167
165
|
}
|
|
168
166
|
|
|
169
|
-
declare class
|
|
167
|
+
declare class Fetchable {
|
|
168
|
+
config: FrigadeConfig;
|
|
169
|
+
constructor(config: FrigadeConfig);
|
|
170
|
+
fetch(path: string, options?: Record<any, any>): Promise<any>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
declare class Flow extends Fetchable {
|
|
170
174
|
/**
|
|
171
175
|
* THe Flow ID / slug of the flow
|
|
172
176
|
*/
|
|
@@ -178,7 +182,7 @@ declare class Flow {
|
|
|
178
182
|
/**
|
|
179
183
|
* Ordered map from Step ID to step data. The `steps` array in `config.yml`
|
|
180
184
|
*/
|
|
181
|
-
steps:
|
|
185
|
+
steps: Map<string, FlowStep>;
|
|
182
186
|
/**
|
|
183
187
|
* The user-facing title of the flow, if defined at the top level of `config.yml`
|
|
184
188
|
*/
|
|
@@ -199,9 +203,12 @@ declare class Flow {
|
|
|
199
203
|
* Whether the flow is started or not
|
|
200
204
|
*/
|
|
201
205
|
isStarted: boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Whether the flow has been skipped or not
|
|
208
|
+
*/
|
|
209
|
+
isSkipped: boolean;
|
|
202
210
|
private flowDataRaw;
|
|
203
|
-
|
|
204
|
-
constructor(internalConfig: InternalConfig, flowDataRaw: FlowDataRaw);
|
|
211
|
+
constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw);
|
|
205
212
|
private initFromRawData;
|
|
206
213
|
/**
|
|
207
214
|
* Function that marks the flow started
|
|
@@ -212,35 +219,34 @@ declare class Flow {
|
|
|
212
219
|
*/
|
|
213
220
|
complete(properties?: Record<string | number, any>): Promise<void>;
|
|
214
221
|
/**
|
|
215
|
-
* Function that
|
|
222
|
+
* Function that marks the flow skipped
|
|
216
223
|
*/
|
|
217
|
-
|
|
224
|
+
skip(properties?: Record<string | number, any>): Promise<void>;
|
|
218
225
|
/**
|
|
219
|
-
*
|
|
226
|
+
* Function that restarts the flow/marks it not started
|
|
220
227
|
*/
|
|
221
|
-
|
|
228
|
+
restart(): Promise<void>;
|
|
222
229
|
/**
|
|
223
230
|
* Get a step by index
|
|
224
231
|
* @param index
|
|
225
232
|
*/
|
|
226
233
|
getStepByIndex(index: number): FlowStep | undefined;
|
|
227
234
|
/**
|
|
228
|
-
* Function that gets current step
|
|
235
|
+
* Function that gets current step
|
|
236
|
+
*/
|
|
237
|
+
getCurrentStep(): FlowStep;
|
|
238
|
+
/**
|
|
239
|
+
* Get the number of completed steps for the current user in the current flow
|
|
229
240
|
*/
|
|
230
|
-
|
|
241
|
+
getNumberOfCompletedSteps(): number;
|
|
231
242
|
private getUserFlowState;
|
|
232
243
|
private refreshUserFlowState;
|
|
233
244
|
}
|
|
234
245
|
|
|
235
|
-
declare class Frigade {
|
|
236
|
-
private apiKey?;
|
|
237
|
-
private userId;
|
|
238
|
-
private organizationId?;
|
|
239
|
-
private config?;
|
|
240
|
-
private hasInitialized;
|
|
241
|
-
private internalConfig?;
|
|
242
|
-
private __instanceId;
|
|
246
|
+
declare class Frigade extends Fetchable {
|
|
243
247
|
private flows;
|
|
248
|
+
private initPromise;
|
|
249
|
+
private onFlowStateChangeHandlers;
|
|
244
250
|
constructor(apiKey: string, config?: FrigadeConfig);
|
|
245
251
|
private init;
|
|
246
252
|
identify(userId: string, properties?: Record<string, any>): Promise<void>;
|
|
@@ -249,10 +255,12 @@ declare class Frigade {
|
|
|
249
255
|
getFlow(flowId: string): Promise<Flow>;
|
|
250
256
|
getFlows(): Promise<Flow[]>;
|
|
251
257
|
reset(): Promise<void>;
|
|
258
|
+
onFlowStateChange(handler: (flow: Flow, newState: UserFlowStatus, previousState: UserFlowStatus) => void): void;
|
|
259
|
+
removeOnFlowStateChangeHandler(handler: (flow: Flow, newState: UserFlowStatus, previousState: UserFlowStatus) => void): void;
|
|
252
260
|
private initIfNeeded;
|
|
253
261
|
private refreshUserFlowStates;
|
|
254
262
|
private refreshFlows;
|
|
255
|
-
private
|
|
263
|
+
private triggerEventHandlers;
|
|
256
264
|
}
|
|
257
265
|
|
|
258
266
|
export { Flow, Frigade };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var
|
|
2
|
+
var R="0.1.2";import N from"cross-fetch";import{v4 as x}from"uuid";var y="COMPLETED_FLOW",D="SKIPPED_FLOW",T="STARTED_FLOW",U="NOT_STARTED_FLOW",w="COMPLETED_STEP",g="STARTED_STEP",v="frigade-last-call-at-",G="frigade-last-call-data-",P="frigade-guest-key",J="guest_";function _(i){return{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json","X-Frigade-SDK-Version":R,"X-Frigade-SDK-Platform":"Javascript"}}}function b(i){return window&&window.localStorage?window.localStorage.getItem(i):null}function C(i,l){window&&window.localStorage&&window.localStorage.setItem(i,l)}function A(){window&&window.localStorage&&Object.keys(window.localStorage).forEach(i=>{i.startsWith("frigade-")&&window.localStorage.removeItem(i)})}async function L(i,l){let t=v+i,e=G+i;if(window&&window.localStorage&&l&&l.body&&l.method==="POST"){let s=b(t),r=b(e);if(s&&r&&r==l.body){let f=new Date(s);if(new Date().getTime()-f.getTime()<1e3)return m()}C(t,new Date().toISOString()),C(e,l.body)}let n;try{n=await N(i,l)}catch(s){return m(s)}return n?n.staus>=400?m(n.statusText):n.json():m()}function m(i){return i&&console.log("Call to Frigade failed",i),{json:()=>({})}}function I(){if(typeof window<"u"&&typeof window.localStorage<"u"){let i=b(P);return i||(i=`${J}${x()}`,window.localStorage.setItem(P,i)),i}}var a={};function d(i){return`${i.__instanceId}-${i.apiKey}:${i.userId??""}:${i.organizationId??""}`}var h=class{constructor(l){this.config={apiKey:"",apiUrl:"//api.frigade.com/v1/public",userId:I(),__instanceId:Math.random().toString(36).substring(7)};this.config={...this.config,...l}}async fetch(l,t){return L(`${this.config.apiUrl}${l}`,{...t??{},..._(this.config.apiKey)})}};var p=class extends h{constructor(t,e){super(t);this.flowDataRaw=e,this.initFromRawData(e)}initFromRawData(t){let e=JSON.parse(t.data),n=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.isSkipped=s.flowState==D,this.steps=new Map,n.forEach((r,f)=>{let c=s.stepStates[r.id],S={...r,isCompleted:c.actionType==w,isStarted:c.actionType==g,isHidden:c.hidden,isBlocked:c.blocked,order:f};S.start=async O=>{let o=this.steps.get(r.id);if(o.isStarted||o.isCompleted)return;o.isStarted=!0;let u={...a[d(this.config)].userFlowStates[this.id]};u.stepStates[o.id].actionType=g,a[d(this.config)].userFlowStates[this.id]=u,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:o.id,data:O??{},createdAt:new Date().toISOString(),actionType:g})}),await this.refreshUserFlowState();let F=this.getUserFlowState();o.isCompleted=F.stepStates[o.id].actionType==w,o.isStarted=F.stepStates[o.id].actionType==g},S.complete=async O=>{let o=this.steps.get(r.id);if(o.isCompleted)return;o.isCompleted=!0;let u={...a[d(this.config)].userFlowStates[this.id]};u.stepStates[o.id].actionType=w,a[d(this.config)].userFlowStates[this.id]=u,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:o.id,data:O??{},createdAt:new Date().toISOString(),actionType:w})}),await this.refreshUserFlowState();let F=this.getUserFlowState();o.isCompleted=F.stepStates[o.id].actionType==w,o.isStarted=F.stepStates[o.id].actionType==g},this.steps.set(r.id,S)})}async start(t){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e={...a[d(this.config)].userFlowStates[this.id]};e.flowState=T,a[d(this.config)].userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:T})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async complete(t){if(this.isCompleted)return;this.isCompleted=!0;let e={...a[d(this.config)].userFlowStates[this.id]};e.flowState=y,a[d(this.config)].userFlowStates[this.id]=e,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:y})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async skip(t){await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t??{},createdAt:new Date().toISOString(),actionType:D})}),await this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)}async restart(){this.isCompleted=!1,this.isCompleted=!0,a[d(this.config)].userFlowStates[this.id]=null,await this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:U})}),await this.refreshUserFlowState()}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let t=this.getUserFlowState(),n=Array.from(this.steps.keys()).find(s=>this.steps.get(s).isCompleted===!1)??Array.from(this.steps.keys())[0];return this.steps.get(n)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getUserFlowState(){return a[d(this.config)].userFlowStates[this.id]}async refreshUserFlowState(){await a[d(this.config)].refreshUserFlowStates()}};var E=class extends h{constructor(t,e){super({apiKey:t,...e});this.flows=[];this.onFlowStateChangeHandlers=[];this.init(this.config)}async init(t){return this.config={...this.config,...t},this.initPromise=(async()=>{await this.refreshUserFlowStates(),await this.refreshFlows()})(),this.initPromise}async identify(t,e){await this.initIfNeeded(),this.config.userId=t,await this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),await this.refreshUserFlowStates()}async group(t,e){await this.initIfNeeded(),this.config.organizationId=t,await this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,properties:e})}),await this.refreshUserFlowStates()}async track(t,e){await this.initIfNeeded(),await this.fetch("/track",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.organizationId,event:t,properties:e})})}async getFlow(t){return await this.initIfNeeded(),this.flows.find(e=>e.id==t)}async getFlows(){return await this.initIfNeeded(),this.flows}async reset(){A(),this.config.userId=I(),this.config.organizationId=void 0}onFlowStateChange(t){this.onFlowStateChangeHandlers.push(t)}removeOnFlowStateChangeHandler(t){this.onFlowStateChangeHandlers=this.onFlowStateChangeHandlers.filter(e=>e!==t)}async initIfNeeded(){return this.initPromise!==null?this.initPromise:this.init(this.config)}async refreshUserFlowStates(){let t=d(this.config);if(!a[t]){let e=this,n={set:function(s,r,f){var c,S;return(s[r]&&((c=s[r])!=null&&c.flowState)&&JSON.stringify(s[r].flowState)!==JSON.stringify(f.flowState)||JSON.stringify((S=s[r])==null?void 0:S.stepStates)!==JSON.stringify(f.stepStates)||JSON.stringify(s[r].shouldTrigger)!==JSON.stringify(f.shouldTrigger))&&e.triggerEventHandlers(s[r],f),s[r]=f,!0}};a[t]={refreshUserFlowStates:async()=>{},userFlowStates:new Proxy({},n)},a[t].refreshUserFlowStates=async()=>{let s=await this.fetch(`/userFlowStates?foreignUserId=${this.config.userId}${this.config.organizationId?`&foreignUserGroupId=${this.config.organizationId}`:""}`);s&&s.data&&s.data.forEach(f=>{a[t].userFlowStates[f.flowId]=f})}}await a[t].refreshUserFlowStates()}async refreshFlows(){this.flows=[];let t=await this.fetch("/flows");t&&t.data&&t.data.forEach(n=>{this.flows.push(new p(this.config,n))})}triggerEventHandlers(t,e){t&&t.flowState!==e.flowState&&this.flows.forEach(n=>{n.id==e.flowId&&this.onFlowStateChangeHandlers.forEach(s=>{s(n,e.flowState,t==null?void 0:t.flowState)})})}};export{p as Flow,E as 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 { 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"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/version.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/Fetchable.ts","../src/core/flow.ts","../src/core/frigade.ts"],"sourcesContent":["export const VERSION_NUMBER = '0.1.2'\n","import { VERSION_NUMBER } from '../core/version'\nimport fetch from 'cross-fetch'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const NOT_STARTED_STEP = 'NOT_STARTED_STEP'\nexport const COMPLETED_FLOW = 'COMPLETED_FLOW'\nexport const SKIPPED_FLOW = 'SKIPPED_FLOW'\nexport const STARTED_FLOW = 'STARTED_FLOW'\nexport const NOT_STARTED_FLOW = 'NOT_STARTED_FLOW'\nexport const COMPLETED_STEP = 'COMPLETED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nexport type StepActionType = 'STARTED_STEP' | 'COMPLETED_STEP' | 'NOT_STARTED_STEP'\nexport type UserFlowStatus = 'NOT_STARTED_FLOW' | 'STARTED_FLOW' | 'COMPLETED_FLOW' | 'SKIPPED_FLOW'\nconst LAST_POST_CALL_AT = 'frigade-last-call-at-'\nconst LAST_POST_CALL_DATA = 'frigade-last-call-data-'\nconst GUEST_KEY = 'frigade-guest-key'\nconst GUEST_PREFIX = 'guest_'\n\nexport function getHeaders(apiKey: string) {\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'X-Frigade-SDK-Version': VERSION_NUMBER,\n 'X-Frigade-SDK-Platform': 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (window && window.localStorage) {\n return window.localStorage.getItem(key)\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (window && window.localStorage) {\n window.localStorage.setItem(key, value)\n }\n}\n\nexport function resetAllLocalStorage() {\n if (window && window.localStorage) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith('frigade-')) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nexport async function gracefulFetch(url: string, options: any) {\n const lastCallAtKey = LAST_POST_CALL_AT + url\n const lastCallDataKey = LAST_POST_CALL_DATA + url\n if (window && window.localStorage && options && options.body && options.method === 'POST') {\n const lastCall = getLocalStorage(lastCallAtKey)\n const lastCallData = getLocalStorage(lastCallDataKey)\n if (lastCall && lastCallData && lastCallData == options.body) {\n const lastCallDate = new Date(lastCall)\n const now = new Date()\n const diff = now.getTime() - lastCallDate.getTime()\n // Throttle consecutive POST calls to 1 second\n if (diff < 1000) {\n return getEmptyResponse()\n }\n }\n setLocalStorage(lastCallAtKey, new Date().toISOString())\n setLocalStorage(lastCallDataKey, options.body)\n }\n\n let response\n try {\n response = await fetch(url, options)\n } catch (error) {\n return getEmptyResponse(error)\n }\n\n if (!response) {\n return getEmptyResponse()\n }\n\n if (response.staus >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n return response.json()\n}\n\nfunction getEmptyResponse(error?: any) {\n if (error) {\n console.log('Call to Frigade failed', error)\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n window.localStorage.setItem(GUEST_KEY, guestId)\n }\n return guestId\n }\n}\n\nexport function fetcher(apiKey: string, path: string, options?: Record<any, any>) {\n return gracefulFetch(`//api.frigade.com/v1/public${path}`, {\n ...(options ?? {}),\n ...getHeaders(apiKey),\n })\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\n\nexport interface FrigadeGlobalState {\n refreshUserFlowStates: () => Promise<void>\n userFlowStates: Record<string, UserFlowState>\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}:${internalConfig.userId ?? ''}:${\n internalConfig.organizationId ?? ''\n }`\n}\n","import { generateGuestId, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../types'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: '//api.frigade.com/v1/public',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(36).substring(7),\n }\n\n constructor(config: FrigadeConfig) {\n this.config = {\n ...this.config,\n ...config,\n }\n }\n\n public async fetch(path: string, options?: Record<any, any>) {\n return gracefulFetch(`${this.config.apiUrl}${path}`, {\n ...(options ?? {}),\n ...getHeaders(this.config.apiKey),\n })\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { FlowDataRaw } from './types'\nimport {\n COMPLETED_FLOW,\n COMPLETED_STEP,\n NOT_STARTED_FLOW,\n SKIPPED_FLOW,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { FlowStep } from './flow-step'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport default class Flow extends Fetchable {\n /**\n * THe Flow ID / slug of the flow\n */\n public id: string\n /**\n * The raw data defined in `config.yml` as a JSON decoded object\n */\n public rawData: Record<any, any>\n /**\n * Ordered map from Step ID to step data. The `steps` array in `config.yml`\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the flow, if defined at the top level of `config.yml`\n */\n public title?: string\n /**\n * The user-facing description of the flow, if defined at the top level of `config.yml`\n */\n public subtitle?: string\n /**\n * The metadata of the flow.\n */\n public metadata: FlowDataRaw\n /**\n * Whether the flow is completed or not\n */\n public isCompleted: boolean\n /**\n * Whether the flow is started or not\n */\n public isStarted: boolean\n /**\n * Whether the flow has been skipped or not\n */\n public isSkipped: boolean\n\n private flowDataRaw: FlowDataRaw\n\n constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw) {\n super(config)\n this.flowDataRaw = flowDataRaw\n this.initFromRawData(flowDataRaw)\n }\n\n private initFromRawData(flowDataRaw: FlowDataRaw) {\n const flowDataYml = JSON.parse(flowDataRaw.data)\n const steps = flowDataYml.steps ?? flowDataYml.data ?? []\n this.id = flowDataRaw.slug\n this.metadata = flowDataRaw\n this.rawData = flowDataYml\n this.title = this.rawData.title\n this.subtitle = this.rawData.subtitle\n\n const userFlowState = this.getUserFlowState()\n\n this.isCompleted = userFlowState.flowState == COMPLETED_FLOW\n this.isStarted = userFlowState.flowState == STARTED_FLOW\n this.isSkipped = userFlowState.flowState == SKIPPED_FLOW\n this.steps = new Map()\n\n steps.forEach((step, index) => {\n const userFlowStateStep = userFlowState.stepStates[step.id]\n const stepObj = {\n ...step,\n isCompleted: userFlowStateStep.actionType == COMPLETED_STEP,\n isStarted: userFlowStateStep.actionType == STARTED_STEP,\n isHidden: userFlowStateStep.hidden,\n isBlocked: userFlowStateStep.blocked,\n order: index,\n } as FlowStep\n\n stepObj.start = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isStarted || currentStep.isCompleted) {\n return\n }\n\n currentStep.isStarted = true\n const clone = {\n ...frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id],\n }\n clone.stepStates[currentStep.id].actionType = STARTED_STEP\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = clone\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n stepObj.complete = async (properties?: Record<string | number, any>) => {\n const currentStep = this.steps.get(step.id)\n\n if (currentStep.isCompleted) {\n return\n }\n\n currentStep.isCompleted = true\n const clone = {\n ...frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id],\n }\n clone.stepStates[currentStep.id].actionType = COMPLETED_STEP\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = clone\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: currentStep.id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_STEP,\n }),\n })\n\n await this.refreshUserFlowState()\n\n const updatedUserFlowState = this.getUserFlowState()\n currentStep.isCompleted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == COMPLETED_STEP\n currentStep.isStarted =\n updatedUserFlowState.stepStates[currentStep.id].actionType == STARTED_STEP\n }\n\n this.steps.set(step.id, stepObj)\n })\n }\n\n /**\n * Function that marks the flow started\n */\n public async start(properties?: Record<string | number, any>) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n\n this.isStarted = true\n const clone = { ...frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] }\n clone.flowState = STARTED_FLOW\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = clone\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow completed\n */\n public async complete(properties?: Record<string | number, any>) {\n if (this.isCompleted) {\n return\n }\n\n this.isCompleted = true\n const clone = { ...frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] }\n clone.flowState = COMPLETED_FLOW\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = clone\n\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: COMPLETED_FLOW,\n }),\n })\n\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that marks the flow skipped\n */\n public async skip(properties?: Record<string | number, any>) {\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: this.getCurrentStep().id,\n data: properties ?? {},\n createdAt: new Date().toISOString(),\n actionType: SKIPPED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n this.initFromRawData(this.flowDataRaw)\n }\n\n /**\n * Function that restarts the flow/marks it not started\n */\n public async restart() {\n this.isCompleted = false\n this.isCompleted = true\n frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates[this.id] = null\n await this.fetch('/flowResponses', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n flowSlug: this.id,\n stepId: 'unknown',\n data: {},\n createdAt: new Date().toISOString(),\n actionType: NOT_STARTED_FLOW,\n }),\n })\n await this.refreshUserFlowState()\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Function that gets current step\n */\n public getCurrentStep(): FlowStep {\n // Find the userFlowState with most recent timestamp\n const userFlowState = this.getUserFlowState()\n\n // TEMP: lastStepId appears to be the last step that a flowState event was recorded for?\n // const lastStepId =\n // userFlowState?.lastStepId?.length > 0 && userFlowState?.lastStepId !== 'unknown'\n // ? userFlowState?.lastStepId\n // : undefined\n\n // TEMP: Return the lowest-ordered incomplete step in the flow\n const lastStepId = Array.from(this.steps.keys()).find(\n (key) => this.steps.get(key).isCompleted === false\n )\n\n const currentStepId = lastStepId ?? Array.from(this.steps.keys())[0]\n return this.steps.get(currentStepId)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.isCompleted).length\n }\n\n private getUserFlowState(): UserFlowState {\n const userFlowStates = frigadeGlobalState[getGlobalStateKey(this.config)].userFlowStates\n return userFlowStates[this.id]\n }\n\n private async refreshUserFlowState() {\n await frigadeGlobalState[getGlobalStateKey(this.config)].refreshUserFlowStates()\n }\n}\n","import { FrigadeConfig, UserFlowState } from '../types'\nimport { generateGuestId, resetAllLocalStorage, UserFlowStatus } from '../shared/utils'\nimport Flow from './flow'\nimport { FlowDataRaw } from './types'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/Fetchable'\n\nexport class Frigade extends Fetchable {\n private flows: Flow[] = []\n private initPromise: Promise<void>\n private onFlowStateChangeHandlers: ((\n flow: Flow,\n newState: UserFlowStatus,\n previousState: UserFlowStatus\n ) => void)[] = []\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n\n this.init(this.config)\n }\n\n private async init(config: FrigadeConfig): Promise<void> {\n this.config = {\n ...this.config,\n ...config,\n }\n\n this.initPromise = (async () => {\n await this.refreshUserFlowStates()\n await this.refreshFlows()\n })()\n\n return this.initPromise\n }\n\n public async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.userId = userId\n await this.fetch('/users', {\n method: 'POST',\n body: JSON.stringify({\n foreignId: this.config.userId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async group(organizationId: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n this.config.organizationId = organizationId\n await this.fetch('/userGroups', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n properties,\n }),\n })\n await this.refreshUserFlowStates()\n }\n\n public async track(event: string, properties?: Record<string, any>): Promise<void> {\n await this.initIfNeeded()\n await this.fetch('/track', {\n method: 'POST',\n body: JSON.stringify({\n foreignUserId: this.config.userId,\n foreignUserGroupId: this.config.organizationId,\n event,\n properties,\n }),\n })\n }\n\n public async getFlow(flowId: string) {\n await this.initIfNeeded()\n\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n return this.flows\n }\n\n public async reset() {\n resetAllLocalStorage()\n this.config.userId = generateGuestId()\n this.config.organizationId = undefined\n }\n\n public onFlowStateChange(\n handler: (flow: Flow, newState: UserFlowStatus, previousState: UserFlowStatus) => void\n ) {\n this.onFlowStateChangeHandlers.push(handler)\n }\n\n public removeOnFlowStateChangeHandler(\n handler: (flow: Flow, newState: UserFlowStatus, previousState: UserFlowStatus) => void\n ) {\n this.onFlowStateChangeHandlers = this.onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n private async initIfNeeded() {\n if (this.initPromise !== null) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n private async refreshUserFlowStates(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (\n (target[key] &&\n target[key]?.flowState &&\n JSON.stringify(target[key].flowState) !== JSON.stringify(value.flowState)) ||\n JSON.stringify(target[key]?.stepStates) !== JSON.stringify(value.stepStates) ||\n JSON.stringify(target[key].shouldTrigger) !== JSON.stringify(value.shouldTrigger)\n ) {\n that.triggerEventHandlers(target[key], value)\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshUserFlowStates: async () => {},\n userFlowStates: new Proxy({}, validator),\n }\n frigadeGlobalState[globalStateKey].refreshUserFlowStates = async () => {\n const userFlowStatesRaw = await this.fetch(\n `/userFlowStates?foreignUserId=${this.config.userId}${\n this.config.organizationId ? `&foreignUserGroupId=${this.config.organizationId}` : ''\n }`\n )\n if (userFlowStatesRaw && userFlowStatesRaw.data) {\n let userFlowStates = userFlowStatesRaw.data as UserFlowState[]\n userFlowStates.forEach((userFlowState) => {\n frigadeGlobalState[globalStateKey].userFlowStates[userFlowState.flowId] = userFlowState\n })\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshUserFlowStates()\n }\n\n private async refreshFlows() {\n this.flows = []\n const flowDataRaw = await this.fetch('/flows')\n if (flowDataRaw && flowDataRaw.data) {\n let flowDatas = flowDataRaw.data as FlowDataRaw[]\n flowDatas.forEach((flowData) => {\n this.flows.push(new Flow(this.config, flowData))\n })\n }\n }\n\n private triggerEventHandlers(\n previousUserFlowState: UserFlowState,\n newUserFlowState: UserFlowState\n ) {\n if (previousUserFlowState && previousUserFlowState.flowState !== newUserFlowState.flowState) {\n this.flows.forEach((flow) => {\n if (flow.id == newUserFlowState.flowId) {\n this.onFlowStateChangeHandlers.forEach((handler) => {\n handler(flow, newUserFlowState.flowState, previousUserFlowState?.flowState)\n })\n }\n })\n }\n }\n}\n"],"mappings":"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","names":["VERSION_NUMBER","fetch","uuidv4","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","STARTED_STEP","LAST_POST_CALL_AT","LAST_POST_CALL_DATA","GUEST_KEY","GUEST_PREFIX","getHeaders","apiKey","VERSION_NUMBER","getLocalStorage","key","setLocalStorage","value","resetAllLocalStorage","gracefulFetch","url","options","lastCallAtKey","lastCallDataKey","lastCall","lastCallData","lastCallDate","getEmptyResponse","response","fetch","error","generateGuestId","guestId","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","path","options","gracefulFetch","getHeaders","Flow","Fetchable","config","flowDataRaw","flowDataYml","steps","userFlowState","COMPLETED_FLOW","STARTED_FLOW","SKIPPED_FLOW","step","index","userFlowStateStep","stepObj","COMPLETED_STEP","STARTED_STEP","properties","currentStep","clone","frigadeGlobalState","getGlobalStateKey","updatedUserFlowState","NOT_STARTED_FLOW","currentStepId","key","Frigade","Fetchable","apiKey","config","userId","properties","organizationId","event","flowId","flow","resetAllLocalStorage","generateGuestId","handler","h","globalStateKey","getGlobalStateKey","frigadeGlobalState","that","validator","target","key","value","_a","_b","userFlowStatesRaw","userFlowState","flowDataRaw","flowData","Flow","previousUserFlowState","newUserFlowState"]}
|
package/package.json
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frigade/js",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The official Javascript SDK for Frigade.",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "./dist/index.js",
|
|
6
7
|
"types": "./dist/index.d.ts",
|
|
7
8
|
"files": [
|
|
8
9
|
"./dist"
|
|
9
10
|
],
|
|
10
11
|
"scripts": {
|
|
11
|
-
"
|
|
12
|
+
"dev": "tsup --watch",
|
|
12
13
|
"test": "jest",
|
|
13
14
|
"lint": "eslint --fix --ext .ts,.tsx .",
|
|
14
|
-
"
|
|
15
|
-
"build": "yarn clean && yarn copy-version-number && tsup && yarn copy-files",
|
|
15
|
+
"build": "yarn copy-version-number && tsup",
|
|
16
16
|
"local-release": "tsup",
|
|
17
|
-
"storybook": "storybook dev -p 6006",
|
|
18
|
-
"build-storybook": "storybook build",
|
|
19
17
|
"copy-version-number": "node ./scripts/copy-version-number.js"
|
|
20
18
|
},
|
|
21
19
|
"repository": {
|
|
@@ -38,14 +36,8 @@
|
|
|
38
36
|
"@babel/plugin-transform-runtime": "^7.19.6",
|
|
39
37
|
"@babel/preset-env": "^7.21.5",
|
|
40
38
|
"@babel/preset-typescript": "^7.21.5",
|
|
41
|
-
"@storybook/addon-essentials": "^7.0.9",
|
|
42
|
-
"@storybook/addon-interactions": "^7.0.9",
|
|
43
|
-
"@storybook/addon-links": "^7.0.9",
|
|
44
|
-
"@storybook/blocks": "^7.0.9",
|
|
45
|
-
"@storybook/testing-library": "^0.0.14-next.2",
|
|
46
39
|
"@types/jest": "^23.3.1",
|
|
47
40
|
"babel-jest": "^29.4.1",
|
|
48
|
-
"copyfiles": "^2.4.1",
|
|
49
41
|
"husky": "^8.0.3",
|
|
50
42
|
"jest": "^29.4.1",
|
|
51
43
|
"jest-config": "^29.3.1",
|
|
@@ -53,7 +45,7 @@
|
|
|
53
45
|
"lint-staged": "^13.0.0",
|
|
54
46
|
"prettier": "^2.4.1",
|
|
55
47
|
"prop-types": "^15.8.1",
|
|
56
|
-
"
|
|
48
|
+
"rimraf": "^5.0.0",
|
|
57
49
|
"ts-jest": "^29.1.0",
|
|
58
50
|
"tsup": "^6.7.0",
|
|
59
51
|
"typedoc": "^0.24.8",
|
package/dist/index.mjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
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
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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":"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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","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"]}
|