@frigade/js 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/utils.ts","../src/shared/state.ts","../src/shared/fetchable.ts","../src/core/flow.ts","../src/version.ts","../src/core/collections.ts","../src/core/frigade.ts","../src/core/types.ts"],"sourcesContent":["import { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { FrigadeGlobalState, frigadeGlobalState } from './state'\nimport { FlowStateContext, FrigadeConfig } from '../core/types'\nimport { SDK_VERSION } from '../version'\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 SKIPPED_STEP = 'SKIPPED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nconst GUEST_KEY = 'frigade-guest-key'\nexport const GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\nconst REDUNDANT_CALL_MESSAGE = 'Redundant call to Frigade API removed'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow({\n config: flow.config,\n id: flow.id,\n })\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(config: FrigadeConfig) {\n return {\n headers: {\n Authorization: `Bearer ${config.apiKey}`,\n 'Content-Type': 'application/json',\n 'x-frigade-sdk-version': config.__platformVersion ?? SDK_VERSION,\n 'x-frigade-sdk-platform': config.__platformName ?? 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n try {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n } catch (e) {\n console.debug('Error getting localStorage:', e)\n return null\n }\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n try {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n } catch (e) {\n console.debug('Error setting localStorage:', e)\n }\n }\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nclass CallQueue {\n private queue: {\n call: string\n time: number\n response?: Promise<Response>\n }[] = []\n private readonly ttlInMS = 250\n private readonly cacheSize = 10\n\n public push(call: string, response?: Promise<Response>) {\n const now = new Date()\n if (this.queue.length >= this.cacheSize) {\n this.queue.shift()\n }\n this.queue.push({\n call: call,\n time: now.getTime(),\n response: response ?? null,\n })\n }\n\n public hasIdenticalRecentCall(callKey: string) {\n const now = new Date()\n this.queue = this.queue.filter((item) => now.getTime() - item.time < this.ttlInMS)\n return this.queue.find((item) => item.call === callKey)\n }\n\n public hasCall(callKey: string) {\n return this.queue.find((item) => item.call === callKey)\n }\n\n public cancelAllPendingRequests() {\n this.queue = []\n }\n}\n\nglobalThis.callQueue = new CallQueue()\n\nexport async function gracefulFetch(url: string, options: any) {\n if (typeof globalThis.fetch !== 'function') {\n return getEmptyResponse(\n \"- Attempted to call fetch() in an environment that doesn't support it.\"\n )\n }\n\n const lastCallDataKey = `${url}${JSON.stringify(options.body ?? {})}`\n let response\n\n const isWebPostRequest = isWeb() && options && options.body && options.method === 'POST'\n\n if (isWebPostRequest) {\n const cachedCall = globalThis.callQueue.hasIdenticalRecentCall(lastCallDataKey)\n\n if (cachedCall != null && cachedCall.response != null) {\n const cachedResponse = await cachedCall.response\n\n response = cachedResponse.clone()\n }\n }\n\n if (!response) {\n try {\n const pendingResponse = fetch(url, options)\n\n if (isWebPostRequest) {\n globalThis.callQueue.push(\n lastCallDataKey,\n // @ts-ignore\n pendingResponse.then((res) => res.clone()).catch(() => getEmptyResponse())\n )\n }\n\n response = await pendingResponse\n if (isWebPostRequest && !globalThis.callQueue.hasCall(lastCallDataKey)) {\n response = getEmptyResponse(REDUNDANT_CALL_MESSAGE)\n }\n } catch (error) {\n return getEmptyResponse(error)\n }\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n if (response.status === 204) {\n return getEmptyResponse()\n }\n\n let body\n try {\n body = await response.json()\n } catch (e) {\n return getEmptyResponse()\n }\n\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nexport function getEmptyResponse(error?: any) {\n if (error) {\n if (error === REDUNDANT_CALL_MESSAGE) {\n console.debug(error)\n } else {\n console.warn('Call to Frigade failed:', error)\n }\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n clone: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n } else {\n return `${GUEST_PREFIX}${uuidv4()}`\n }\n}\n\nexport function isWeb() {\n return (\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.localStorage !== 'undefined'\n )\n}\n\nexport function getContext(state: FrigadeGlobalState): FlowStateContext {\n let context: FlowStateContext = {\n registeredCollectionIds: Array.from(state.registeredCollectionIds),\n }\n\n if (!isWeb()) {\n return context\n }\n\n return {\n url: state.currentUrl,\n userAgent: navigator.userAgent,\n ...context,\n }\n}\n","import { FlowStates, FlowStep, FrigadeConfig, SessionDTO, StatefulFlow } from '../core/types'\nimport { Flow } from '../core/flow'\nimport type { Collections } from '../core/collections'\n\nexport interface FrigadeGlobalState {\n refreshStateFromAPI: (\n overrideFlowStatesRaw?: FlowStates,\n cancelPendingRequests?: boolean\n ) => Promise<void>\n flowStates: Record<string, StatefulFlow>\n collections: Collections\n registeredCollectionIds: Set<string>\n onFlowStateChangeHandlerWrappers: Map<\n (flow: Flow, previousFlow: Flow) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onStepStateChangeHandlerWrappers: Map<\n (step: FlowStep, previousStep: FlowStep) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[]\n previousFlows: Map<string, Flow>\n variables: Record<string, Record<string, any>>\n lastFlowSyncDate: Map<string, Date>\n pendingRequests: Map<string, number>\n config: FrigadeConfig\n currentUrl: string\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}`\n}\n","import { generateGuestId, getEmptyResponse, getHeaders, gracefulFetch } from './utils'\nimport { FrigadeConfig } from '../core/types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(12).substring(4),\n generateGuestId: true,\n __refreshIntervalInMS: 100,\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(this.getAPIUrl(path), {\n keepalive: true,\n ...(options ?? {}),\n ...getHeaders(this.config),\n })\n }\n\n private getAPIUrl(path: string) {\n return `${this.config.apiUrl.replace(/\\/$/, '')}/${path.replace(/^\\//, '')}`\n }\n\n /**\n * @ignore\n */\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade has not yet been initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import {\n FlowActionType,\n FlowStateDTO,\n FlowStates,\n FlowStep,\n FlowType,\n FrigadeConfig,\n PropertyPayload,\n StatefulFlow,\n StatefulStep,\n} from './types'\nimport {\n clone,\n cloneFlow,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n getContext,\n NOT_STARTED_FLOW,\n NOT_STARTED_STEP,\n SKIPPED_FLOW,\n SKIPPED_STEP,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { Fetchable } from '../shared/fetchable'\nimport { CollectionsRegistryCallback } from './collections'\n\nexport class Flow extends Fetchable {\n /**\n * The Flow's ID.\n */\n public id: string\n /**\n * The version of the Flow.\n */\n public version: number\n /**\n * The Flow's component ID.\n */\n public componentId: string\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The type of the Flow such as `TOUR` or `CHECKLIST`.\n */\n public type: FlowType\n /**\n * @ignore Internal use only.\n * Props to pass through to the Flow Component in the React SDK.\n */\n public props?: Record<string, unknown> = {}\n /**\n * The raw metadata of the Flow. Contains all properties defined in the Flow's YAML config as well as the current state of the Flow.\n * Generally this should only be used when building custom components to access custom high-level props on the Flow.\n */\n public rawData: StatefulFlow\n /**\n * Whether the Flow is completed or not.\n */\n public isCompleted: boolean\n /**\n * Whether the Flow is started or not.\n */\n public isStarted: boolean\n /**\n * Whether the Flow has been skipped or not.\n */\n public isSkipped: boolean\n /**\n * @ignore\n */\n private _isVisible: boolean = false\n /**\n * Whether the Flow is visible to the user based on the current user/group's state.\n * This function will return `false` if the user has already completed or dismissed the Flow or if the user\n * does not match the Flow's targeting/audience.\n */\n get isVisible() {\n return this._isVisible\n\n // if (this._isVisible === false) {\n // return false\n // }\n\n // return this.getGlobalState().collections.isFlowVisible(this.id)\n }\n set isVisible(visible: boolean) {\n this._isVisible = visible\n }\n\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n constructor({ config, id }: { config: FrigadeConfig; id: string }) {\n super(config)\n this.id = id\n this.init()\n }\n\n /**\n * Reload the Flow data from the server\n */\n reload() {\n this.init()\n }\n\n /**\n * @ignore\n */\n resyncState(overrideStatefulFlow?: StatefulFlow) {\n const statefulFlow = clone(overrideStatefulFlow ?? this.getStatefulFlow())\n\n this.rawData = statefulFlow\n this.title = statefulFlow?.data?.title\n this.subtitle = statefulFlow?.data?.subtitle\n this.type = statefulFlow?.data?.type\n this.props = statefulFlow?.data?.props ?? {}\n this.version = statefulFlow?.version\n this.isCompleted = statefulFlow.$state.completed\n this.isStarted = statefulFlow.$state.started\n this.isSkipped = statefulFlow.$state.skipped\n this._isVisible = statefulFlow.$state.visible\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n const existingStep = this.steps?.get(step.id)\n if (existingStep) {\n Object.keys(stepObj).forEach((key) => {\n existingStep[key] = stepObj[key]\n })\n }\n })\n\n if (this.getGlobalState().variables[this.id]) {\n this.applyVariablesInternal(this.getGlobalState().variables[this.id] ?? {})\n } else {\n this.applyVariablesInternal({})\n }\n }\n\n /**\n * @ignore\n */\n private initStepFromStatefulStep(step: StatefulStep, index: number) {\n return {\n ...step,\n flow: this,\n $state: {\n ...step.$state,\n lastActionAt: step.$state.lastActionAt ? new Date(step.$state.lastActionAt) : undefined,\n },\n order: index,\n } as Partial<FlowStep>\n }\n\n /**\n * @ignore\n */\n private init() {\n const statefulFlow = this.getStatefulFlow()\n const newSteps = new Map<string, FlowStep>()\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n stepObj.start = async (properties?: PropertyPayload) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.$state.started) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n copy.$state.lastActionAt = new Date()\n copy.$state.currentStepId = thisStep.id\n copy.$state.currentStepIndex = thisStep.order\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(STARTED_STEP, properties, thisStep.id)\n }\n\n const internalComplete = async (\n eventType: 'complete' | 'skip',\n properties?: PropertyPayload,\n optimistic: boolean = true\n ) => {\n const thisStep = this.steps.get(step.id)\n\n if ((thisStep.$state.completed || thisStep.$state.skipped) && optimistic) {\n // mark the next step started to advance.\n let nextStep: FlowStep | undefined = this.getStepByIndex(thisStep.order + 1)\n while (nextStep && !nextStep.$state.visible) {\n if (nextStep.order === this.steps.size - 1) {\n break\n }\n nextStep = this.getStepByIndex(nextStep.order + 1)\n }\n if (nextStep) {\n // optimistically mark the next step as started\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.currentStepId = this.getStepByIndex(thisStep.order + 1).id\n copy.$state.currentStepIndex = thisStep.order + 1\n // mark the next step as started\n copy.data.steps[thisStep.order + 1].$state.started = true\n\n this.getGlobalState().flowStates[this.id] = copy\n\n await this.sendFlowStateToAPI(STARTED_STEP, undefined, nextStep.id)\n\n this.resyncState()\n }\n\n return\n }\n\n const isLastStep = this.getCurrentStepOrder() + 1 === this.getNumberOfAvailableSteps()\n const isLastIncompleteStep =\n Array.from(this.steps.values()).filter(\n (step) => step.$state.visible && !step.$state.completed && !step.$state.skipped\n ).length === 1 && isLastStep\n\n if (optimistic) {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n\n copy.$state.started = true\n if (eventType == 'complete') {\n copy.data.steps[thisStep.order].$state.completed = true\n } else {\n copy.data.steps[thisStep.order].$state.skipped = true\n }\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n\n if (!isLastStep) {\n const nextStepIndex = this.getNextVisibleStepIndexAfterIndex(thisStep.order)\n if (nextStepIndex !== -1) {\n copy.$state.currentStepId = this.getStepByIndex(nextStepIndex).id\n copy.$state.currentStepIndex = nextStepIndex\n copy.data.steps[nextStepIndex].$state.started = true\n }\n }\n if (isLastIncompleteStep) {\n copy.$state.completed = true\n copy.$state.visible = false\n }\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (isLastIncompleteStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n }\n\n await this.sendFlowStateToAPI(\n eventType == 'complete' ? COMPLETED_STEP : SKIPPED_STEP,\n properties,\n thisStep.id\n )\n if (isLastIncompleteStep) {\n await this.sendFlowStateToAPI(COMPLETED_FLOW, properties)\n }\n }\n\n stepObj.complete = async (properties?: PropertyPayload, optimistic: boolean = true) => {\n await internalComplete('complete', properties, optimistic)\n }\n\n stepObj.skip = async (properties?: PropertyPayload, optimistic: boolean = true) => {\n await internalComplete('skip', properties, optimistic)\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.$state.completed) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = false\n copy.data.steps[thisStep.order].$state.completed = false\n copy.data.steps[thisStep.order].$state.lastActionAt = undefined\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(NOT_STARTED_STEP, undefined, thisStep.id)\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.$state.completed !== previousStep?.$state.completed ||\n thisStep.$state.started !== previousStep?.$state.started ||\n thisStep.$state.visible !== previousStep?.$state.visible ||\n thisStep.$state.blocked !== previousStep?.$state.blocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj as FlowStep)\n })\n this.steps = newSteps\n\n this.resyncState()\n }\n\n /**\n * Marks the flow started\n */\n public async start(properties?: PropertyPayload) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowStarted()\n\n await this.sendFlowStateToAPI(STARTED_FLOW, properties)\n }\n\n /**\n * Marks the flow completed\n */\n public async complete(properties?: PropertyPayload) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n await this.sendFlowStateToAPI(COMPLETED_FLOW, properties)\n }\n\n /**\n * Marks the flow skipped\n */\n public async skip(properties?: PropertyPayload) {\n if (this.isSkipped) {\n return\n }\n this.optimisticallyMarkFlowSkipped()\n await this.sendFlowStateToAPI(SKIPPED_FLOW, properties)\n }\n\n /**\n * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: PropertyPayload) {\n const nextStep = this.getStepByIndex(\n this.getNextVisibleStepIndexAfterIndex(this.getCurrentStepIndex())\n )\n\n if (nextStep) {\n await nextStep.start(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: PropertyPayload) {\n // Continue back until a visible step is found\n let previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n while (previousStep && !previousStep.$state.visible) {\n if (previousStep.order === 0) {\n break\n }\n previousStep = this.getStepByIndex(previousStep.order - 1)\n }\n\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n await this.sendFlowStateToAPI(NOT_STARTED_FLOW)\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Gets current step. If the current step is not visible, it will return the first visible step after it.\n * If no steps are visible, it will return undefined.\n */\n public getCurrentStep(): FlowStep | undefined {\n let currentStep = this.steps.get(this.getStatefulFlow().$state.currentStepId)\n if (currentStep) {\n return currentStep\n }\n currentStep = this.getFirstVisibleStep()\n\n return currentStep\n }\n\n /**\n * @ignore\n */\n private getFirstVisibleStep() {\n return this.getStepByIndex(this.getNextVisibleStepIndexAfterIndex(-1))\n }\n\n /**\n * @ignore\n */\n private getNextVisibleStepIndexAfterIndex(index: number): number {\n const steps = Array.from(this.steps.values())\n for (let i = index + 1; i < steps.length; i++) {\n if (steps[i].$state.visible) {\n return i\n }\n }\n return -1\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.completed).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.visible).length\n }\n\n /**\n * Returns the current step's order based on the number of available steps.\n * Works similar to getCurrentStepIndex but takes into account hidden steps due to visibilityCriteria.\n */\n public getCurrentStepOrder(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.values())\n .filter((step) => step.$state.visible)\n .indexOf(currentStep)\n }\n\n /**\n * Get the progress of the flow as a number between 0 and 1. Useful when rendering a progress bar.\n */\n public getProgress(): number {\n return (this.getNumberOfCompletedSteps() || 0) / (this.getNumberOfAvailableSteps() || 1)\n }\n\n /**\n * @ignore\n * @deprecated Use `frigade.on('flow.complete' | 'flow.skip' | 'flow.restart' | 'flow.start', handler)` instead.\n */\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (flow.id === this.id) {\n if (\n flow.isCompleted !== previousFlow?.isCompleted ||\n flow.isStarted !== previousFlow?.isStarted ||\n flow.isSkipped !== previousFlow?.isSkipped ||\n flow.isVisible !== previousFlow?.isVisible ||\n JSON.stringify(flow.steps) !== JSON.stringify(previousFlow?.steps)\n ) {\n handler(flow, previousFlow)\n }\n }\n }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n /**\n * @ignore\n */\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n /**\n * Apply variables to the flow. This will replace any `${variable}` in the title, subtitle, and step fields with the value of the variable.\n * @param variables A record of variables to apply to the flow.\n */\n public applyVariables(variables: Record<string, any>) {\n this.applyVariablesInternal(variables, true)\n }\n\n /**\n * @ignore\n */\n private applyVariablesInternal(variables: Record<string, any>, resyncState: boolean = false) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n if (!variables[variable]) {\n // set the variable to blank string as it was not found\n str = str.replace(match, '')\n return\n }\n str = str.replace(match, variables[variable])\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n const applyVariablesToStep = (step: any) => {\n if (!step) {\n return\n }\n\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n } else if (typeof step[key] === 'object') {\n applyVariablesToStep(step[key])\n } else if (Array.isArray(step[key])) {\n step[key].forEach((item: any) => {\n applyVariablesToStep(item)\n })\n }\n })\n }\n\n if (this.steps) {\n this.steps.forEach((step) => {\n try {\n console\n applyVariablesToStep(step)\n } catch (e) {\n // ignore any failures\n }\n })\n }\n\n this.getGlobalState().variables[this.id] = {\n ...this.getGlobalState().variables[this.id],\n ...variables,\n }\n\n if (resyncState) {\n this.resyncState()\n }\n }\n\n /**\n * @ignore\n */\n private getStatefulFlow(): StatefulFlow {\n const userFlowStates = this.getGlobalState().flowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowCompleted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = true\n copy.$state.started = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowStarted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.started = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n private async sendFlowStateToAPI(\n action: FlowActionType,\n data?: PropertyPayload,\n stepId?: string\n ) {\n const date = new Date()\n this.getGlobalState().lastFlowSyncDate[this.id] = date\n this.getGlobalState().pendingRequests[this.id] =\n (this.getGlobalState().pendingRequests[this.id] ?? 0) + 1\n const flowStatesRaw: FlowStates = await this.fetch('/v1/public/flowStates', {\n method: 'POST',\n body: JSON.stringify({\n userId: this.getGlobalState().config.userId,\n groupId: this.getGlobalState().config.groupId,\n flowSlug: this.id,\n stepId: stepId,\n data: data ? data : {},\n actionType: action,\n createdAt: date,\n context: getContext(this.getGlobalState()),\n } as FlowStateDTO),\n })\n this.getGlobalState().pendingRequests[this.id] -= 1\n // if a newer request was sent, use that one.\n // except if there are other pending requests\n if (\n date < this.getGlobalState().lastFlowSyncDate[this.id] ||\n this.getGlobalState().pendingRequests[this.id] > 0\n ) {\n return\n }\n await this.getGlobalState().refreshStateFromAPI(flowStatesRaw)\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowSkipped() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.skipped = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n public register(callback?: CollectionsRegistryCallback) {\n const globalState = this.getGlobalState()\n\n globalState.collections.register(this.id, (visible) => {\n const prevFlow = this.getGlobalState().previousFlows.get(this.id)\n\n if (prevFlow?._isVisible !== visible) {\n // TODO: Store these in a hash so we can grab this flow's handler and call it\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n handler(this, prevFlow)\n this.getGlobalState().previousFlows.set(this.id, cloneFlow(this))\n })\n }\n\n callback?.(visible)\n })\n }\n\n public unregister() {\n if (!this.getGlobalState().collections) {\n return\n }\n this.getGlobalState().collections.unregister(this.id)\n }\n}\n","export const SDK_VERSION = '0.9.0';","import type { Flow } from './flow'\n\nexport type CollectionsRegistryCallback = (visible: boolean) => void\n\nexport type CollectionsRegistryBatch = [string, CollectionsRegistryCallback][]\n\nexport interface CollectionsRegistryItem {\n visible: boolean\n visited: boolean\n callback: CollectionsRegistryCallback\n}\n\nexport interface Collection {\n allowedComponents: string[]\n collectionType: 'DEFAULT' | 'CUSTOM'\n flows: {\n flowId: string\n visible: boolean\n }[]\n}\n\nexport interface EnrichedCollection extends Omit<Collection, 'flows'> {\n flows: Array<\n Collection['flows'][number] & {\n flow: Flow\n }\n >\n}\n\nexport type CollectionsList = Map<string, Collection>\n\nexport class Collections {\n private readonly registry: Map<string, CollectionsRegistryItem> = new Map()\n private registryStateLocked: boolean = false\n private collections: CollectionsList = new Map()\n private flowsInCollections: Set<string> = new Set()\n private hasChanges: boolean = false\n\n constructor(collectionsData: CollectionsList) {\n this.ingestCollectionsData(collectionsData)\n }\n\n getCollection(collectionId: string) {\n return this.collections.get(collectionId)\n }\n\n getCollections() {\n return this.collections\n }\n\n collectionsHaveChanged() {\n return this.hasChanges\n }\n\n ingestCollectionsData(collectionsData: CollectionsList) {\n this.hasChanges = true\n\n this.checkIfCollectionsHaveChanged(collectionsData)\n\n if (!this.hasChanges) {\n return\n }\n\n this.collections = collectionsData\n\n for (const [, collection] of this.collections) {\n for (const { flowId } of collection.flows) {\n this.flowsInCollections.add(flowId)\n }\n }\n\n if (this.registry.size > 0) {\n if (!this.registryStateLocked) {\n this.resetRegistryState()\n }\n\n this.processCollections()\n }\n\n this.fireCallbacks()\n }\n\n private checkIfCollectionsHaveChanged(newCollectionsData: CollectionsList) {\n const previousCollections = this.collections\n const newCollections = newCollectionsData\n\n if (previousCollections.size !== newCollections.size) {\n this.hasChanges = true\n }\n\n for (const [collectionId, collection] of previousCollections) {\n const newCollection = newCollections.get(collectionId)\n if (collection.flows.length !== newCollection.flows.length) {\n this.hasChanges = true\n break\n }\n\n for (let i = 0; i < collection.flows.length; i++) {\n if (\n collection.flows[i].flowId !== newCollection.flows[i].flowId ||\n collection.flows[i].visible !== newCollection.flows[i].visible\n ) {\n this.hasChanges = true\n break\n }\n }\n }\n }\n\n fireCallbacks() {\n for (const [flowId, { callback }] of this.registry) {\n if (typeof callback === 'function') {\n callback(this.isFlowVisible(flowId))\n }\n }\n }\n\n isFlowVisible(flowId: string) {\n const registeredFlow = this.registry.get(flowId)\n const flowInCollections = this.flowsInCollections.has(flowId)\n\n if (registeredFlow == null || !flowInCollections) {\n return true\n }\n\n return registeredFlow.visible\n }\n\n lockRegistryState() {\n this.registryStateLocked = true\n }\n\n unlockRegistryState() {\n this.registryStateLocked = false\n }\n\n resetRegistryState() {\n for (const [flowId, item] of this.registry) {\n item.visible = false\n item.visited = false\n\n this.registry.set(flowId, item)\n }\n }\n\n processCollections() {\n for (const [, collection] of this.collections) {\n for (const { flowId, visible: visibleAPIOverride } of collection.flows) {\n const registeredFlow = this.registry.get(flowId)\n\n // If this flow in the collection isn't registered, we have no opinion on it yet\n if (registeredFlow == null) {\n continue\n }\n\n // The API can force a flow to be hidden due to cool-offs, etc.\n if (visibleAPIOverride === false && registeredFlow.visible !== true) {\n this.visit(flowId, false)\n continue\n }\n\n // If this flow was processed in a previous collection and the registry is locked,\n // visibility shouldn't change until next time we run processCollections\n if (registeredFlow.visited && this.registryStateLocked) {\n continue\n }\n\n const flowIdsInThisCollection = collection.flows\n .map(({ flowId: otherFlowId }) => otherFlowId)\n .filter((otherFlowId) => otherFlowId !== flowId)\n\n // If another flow in this collection has been visited already and is visible...\n // const anotherFlowInThisCollectionIsVisible = flowIdsInThisCollection.some((otherId) => {\n // const { visible: otherVisible, visited: otherVisited } = this.registry.get(otherId) ?? {}\n\n // return otherVisible && otherVisited\n // })\n\n // ...then this flow is hidden\n // if (anotherFlowInThisCollectionIsVisible) {\n // this.visit(flowId, false)\n\n // continue\n // }\n\n // No other flows are visible, so this flow is visible by default\n this.visit(flowId)\n }\n }\n }\n\n register(flowId: string | CollectionsRegistryBatch, callback?: CollectionsRegistryCallback) {\n if (Array.isArray(flowId)) {\n this.batchRegister(flowId)\n return\n }\n\n this.registry.set(flowId, {\n callback: callback ?? (() => {}),\n visible: false,\n visited: false,\n })\n\n if (!this.registryStateLocked) {\n this.resetRegistryState()\n }\n\n this.processCollections()\n\n this.fireCallbacks()\n }\n\n batchRegister(flowIds: CollectionsRegistryBatch) {\n flowIds.forEach(([flowId, callback]) => {\n this.registry.set(flowId, {\n callback: callback ?? (() => {}),\n visible: false,\n visited: false,\n })\n })\n\n if (!this.registryStateLocked) {\n this.resetRegistryState()\n }\n\n this.processCollections()\n\n this.lockRegistryState()\n\n this.fireCallbacks()\n }\n\n unregister(flowId: string) {\n this.registry.delete(flowId)\n\n this.resetRegistryState()\n this.processCollections()\n\n this.fireCallbacks()\n }\n\n private visit(flowId: string, visible: boolean = true) {\n const item = this.registry.get(flowId) ?? {\n callback: () => {},\n visible,\n visited: true,\n }\n\n item.visible = visible\n item.visited = true\n\n this.registry.set(flowId, item)\n }\n}\n","import {\n FlowChangeEvent,\n FlowChangeEventHandler,\n FlowStateDTO,\n FlowStates,\n FlowStep,\n FrigadeConfig,\n PropertyPayload,\n SessionDTO,\n StatefulFlow,\n} from './types'\nimport {\n clearCache,\n cloneFlow,\n getContext,\n GUEST_PREFIX,\n isWeb,\n resetAllLocalStorage,\n} from '../shared/utils'\nimport { Flow } from './flow'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/fetchable'\nimport {\n type Collection,\n Collections,\n type CollectionsList,\n type CollectionsRegistryBatch,\n type EnrichedCollection,\n} from './collections'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n /**\n * @ignore\n */\n private lastSessionDTO?: SessionDTO\n /**\n * @ignore\n */\n private eventHandlers: Map<FlowChangeEvent, FlowChangeEventHandler[]> = new Map()\n /**\n * @ignore\n */\n private refreshTimeout: ReturnType<typeof setTimeout> | null = null\n /**\n * @ignore\n */\n private queuedRefresh: boolean = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = () => {\n if (document.visibilityState === 'visible') {\n this.queueRefreshStateFromAPI()\n }\n }\n\n /**\n * @ignore\n */\n private queueRefreshStateFromAPI() {\n this.queuedRefresh = true\n if (this.refreshTimeout) {\n return\n }\n\n this.refreshTimeout = setTimeout(async () => {\n if (this.queuedRefresh) {\n this.getGlobalState().currentUrl = window.location.href\n await this.refreshStateFromAPI()\n this.queuedRefresh = false\n }\n this.refreshTimeout = null\n }, this.getGlobalState().config.__refreshIntervalInMS)\n }\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb() && this.config.syncOnWindowUpdates !== false) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n // @ts-ignore\n if (window.navigation) {\n // @ts-ignore\n window.navigation.addEventListener('navigate', async (event) => {\n try {\n if (this.getGlobalState().currentUrl === event.destination.url) {\n return\n }\n // if the new base url is the same but with a hashtag, don't refresh the state as the page has not changed.\n if (\n event.destination.url &&\n this.getGlobalState().currentUrl &&\n event.destination.url.split('#')[0] === this.getGlobalState().currentUrl.split('#')[0]\n ) {\n return\n }\n this.queueRefreshStateFromAPI()\n } catch (e) {}\n })\n }\n }\n }\n\n /**\n * Gets the current configuration.\n * See [FrigadeConfig](https://github.com/FrigadeHQ/javascript/blob/main/packages/js-api/src/core/types.ts#L240) for a list of available options.\n */\n getConfig() {\n return this.config\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\n */\n private async init(config: FrigadeConfig): Promise<void> {\n this.updateConfig({\n ...this.config,\n ...config,\n })\n\n if (!this.config.userId) {\n return\n }\n\n this.initPromise = (async () => {\n if (!this.config.__readOnly) {\n if (this.config.userId?.startsWith(GUEST_PREFIX)) {\n // do nothing\n } else if (this.config.userId && this.config.groupId) {\n await this.session({\n userId: this.config.userId,\n groupId: this.config.groupId,\n userProperties: this.config.userProperties,\n groupProperties: this.config.groupProperties,\n })\n } else if (this.config.userId) {\n await this.session({\n userId: this.config.userId,\n userProperties: this.config.userProperties,\n })\n }\n }\n await this.refreshStateFromAPI()\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: PropertyPayload): Promise<void> {\n if (userId !== this.config.userId) {\n await this.updateConfig({ ...this.config, userId })\n await this.reload()\n }\n\n await this.initIfNeeded()\n const isNewSession = await this.session({\n userId: this.config.userId,\n userProperties: properties,\n })\n if (isNewSession) {\n await this.resync()\n }\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId?: string, properties?: PropertyPayload): Promise<void> {\n await this.initIfNeeded()\n this.updateConfig({ ...this.config, groupId })\n await this.session({\n userId: this.config.userId,\n groupId: this.config.groupId,\n groupProperties: properties,\n })\n await this.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: PropertyPayload): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.session({\n userId: this.config.userId,\n groupId: this.config.groupId,\n groupEvents: [\n {\n event,\n properties,\n },\n ],\n userEvents: [\n {\n event,\n properties,\n },\n ],\n })\n } else if (this.config.userId) {\n await this.session({\n userId: this.config.userId,\n userEvents: [\n {\n event,\n properties,\n },\n ],\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n private async session(sessionDTO: SessionDTO) {\n const lastSessionDTO = this.lastSessionDTO\n\n if (lastSessionDTO && JSON.stringify(lastSessionDTO) === JSON.stringify(sessionDTO)) {\n return false\n }\n\n await this.fetch('/v1/public/sessions', {\n method: 'POST',\n body: JSON.stringify(sessionDTO),\n })\n\n this.lastSessionDTO = sessionDTO\n\n return true\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\n */\n public async getFlow(flowId: string) {\n if (\n this.getConfig().generateGuestId === false &&\n this.getConfig().userId &&\n this.getConfig().userId.startsWith(GUEST_PREFIX)\n ) {\n return undefined\n }\n await this.initIfNeeded()\n\n return this.getFlowSync(flowId)\n }\n\n /**\n * @ignore\n */\n public getFlowSync(flowId: string) {\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n if (\n this.config.generateGuestId === false &&\n this.getConfig().userId?.startsWith(GUEST_PREFIX)\n ) {\n return []\n }\n return this.flows\n }\n\n public async getCollection(collectionId: string) {\n await this.initIfNeeded()\n const collection = this.getGlobalState().collections.getCollection(collectionId)\n\n if (collection == null) {\n return undefined\n }\n\n this.registerCollection(collectionId)\n\n const enrichedFlows = await Promise.all(\n collection.flows.map(async (item) => ({\n ...item,\n flow: await this.getFlow(item.flowId),\n }))\n )\n\n collection.flows = enrichedFlows\n\n return collection as EnrichedCollection\n }\n\n public async registerCollection(collectionId: string) {\n await this.initIfNeeded()\n if (collectionId) {\n this.getGlobalState().registeredCollectionIds.add(collectionId)\n }\n }\n\n /**\n * @ignore\n */\n public getCollectionSync(collectionId: string): Collection | undefined {\n const collection = this.getGlobalState().collections.getCollection(collectionId)\n\n if (collection == null) {\n return undefined\n }\n\n this.getGlobalState().registeredCollectionIds.add(collectionId)\n\n return collection\n }\n\n /**\n * @ignore\n */\n public getCollectionsSync(): CollectionsList | undefined {\n return this.getGlobalState().collections.getCollections()\n }\n\n public async getCollections(): Promise<CollectionsList | undefined> {\n await this.initIfNeeded()\n\n if (!this.config.userId && this.config.generateGuestId === false) {\n return undefined\n }\n\n const collections = this.getGlobalState().collections.getCollections()\n\n if (collections == null) {\n return undefined\n }\n\n return collections\n }\n\n /**\n * Reload the current state of the flows by calling the Frigade API.\n * This will trigger all event handlers.\n * @param config optional config to use when reloading. If not passed, the current config will be used.\n */\n public async reload(config?: FrigadeConfig) {\n resetAllLocalStorage()\n clearCache()\n if (config) {\n await this.updateConfig(config)\n this.mockFlowStates(getGlobalStateKey(this.config))\n }\n this.initPromise = null\n await this.init(this.config)\n this.triggerAllLegacyEventHandlers()\n this.triggerAllEventHandlers()\n }\n\n /**\n * @ignore\n */\n private triggerAllLegacyEventHandlers() {\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n private triggerAllEventHandlers() {\n this.flows.forEach((flow) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n this.triggerEventHandlers(flow.rawData, lastFlow?.rawData)\n })\n }\n\n private async resync() {\n await this.refreshStateFromAPI()\n }\n\n /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @deprecated Use `frigade.on` instead.\n * @param handler\n */\n public async onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Event handler that captures all changes that happen to the state of the Flows. Use `flow.any` to capture all events.\n * @param event `flow.any` | `flow.complete` | `flow.restart` | `flow.skip` | `flow.start` | `step.complete` | `step.skip` | `step.reset` | `step.start`\n * @param handler\n */\n public async on(event: FlowChangeEvent, handler: FlowChangeEventHandler) {\n this.eventHandlers.set(event, [...(this.eventHandlers.get(event) ?? []), handler])\n }\n\n /**\n * Removes the given handler.\n * @param event `flow.any` | `flow.complete` | `flow.restart` | `flow.skip` | `flow.start` | `step.complete` | `step.skip` | `step.reset` | `step.start`\n * @param handler\n */\n public async off(event: FlowChangeEvent, handler: FlowChangeEventHandler) {\n this.eventHandlers.set(\n event,\n (this.eventHandlers.get(event) ?? []).filter((h) => h !== handler)\n )\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\n */\n public async removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n /**\n * @ignore\n */\n private async initIfNeeded() {\n if (this.initPromise) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n /**\n * @ignore\n */\n private async refreshStateFromAPI(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (target[key]) {\n const previousState = target[key] as StatefulFlow\n const newState = value as StatefulFlow\n if (JSON.stringify(previousState) !== JSON.stringify(newState)) {\n that.triggerDeprecatedEventHandlers(newState, previousState)\n that.triggerEventHandlers(newState, previousState)\n }\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshStateFromAPI: async () => {},\n collections: new Collections(new Map()),\n registeredCollectionIds: new Set(),\n flowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n variables: {},\n config: this.config,\n currentUrl: isWeb() ? window.location.href : '',\n pendingRequests: new Map(),\n lastFlowSyncDate: new Map(),\n }\n\n if (this.config.__readOnly && this.config.__flowStateOverrides) {\n this.mockFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshStateFromAPI = async (\n overrideFlowStateRaw?: FlowStates\n ) => {\n if (this.config.__readOnly) {\n return\n }\n\n const flowStateRaw: FlowStates = overrideFlowStateRaw\n ? overrideFlowStateRaw\n : await this.fetch('/v1/public/flowStates', {\n method: 'POST',\n body: JSON.stringify({\n userId: this.getGlobalState().config.userId,\n groupId: this.getGlobalState().config.groupId,\n context: getContext(this.getGlobalState()),\n } as FlowStateDTO),\n })\n\n const collectionsData: CollectionsList = new Map()\n\n flowStateRaw.collections?.computedOrder?.forEach(\n ({ allowedComponents, collectionId, collectionType, flowId, visible }) => {\n const currentCollection: Collection = collectionsData.get(collectionId) ?? {\n allowedComponents,\n collectionType,\n flows: [],\n }\n\n currentCollection.flows.push({\n flowId,\n visible,\n })\n\n collectionsData.set(collectionId, currentCollection)\n }\n )\n\n if (collectionsData.size > 0) {\n frigadeGlobalState[globalStateKey].collections.ingestCollectionsData(collectionsData)\n if (\n frigadeGlobalState[globalStateKey].collections.collectionsHaveChanged() &&\n // Necessary check to prevent race condition between flow state and collection state\n !overrideFlowStateRaw\n ) {\n this.triggerAllLegacyEventHandlers()\n this.triggerAllEventHandlers()\n }\n }\n\n if (flowStateRaw && flowStateRaw.eligibleFlows) {\n flowStateRaw.eligibleFlows.forEach((statefulFlow) => {\n frigadeGlobalState[globalStateKey].flowStates[statefulFlow.flowSlug] = statefulFlow\n if (!this.flows.find((flow) => flow.id == statefulFlow.flowSlug)) {\n this.flows.push(\n new Flow({\n config: this.config,\n id: statefulFlow.flowSlug,\n })\n )\n } else {\n this.flows.forEach((flow) => {\n if (flow.id == statefulFlow.flowSlug) {\n flow.resyncState(statefulFlow)\n }\n })\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshStateFromAPI(undefined)\n }\n\n /**\n * @ignore\n */\n private mockFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowStateOverrides).forEach((flowId) => {\n frigadeGlobalState[globalStateKey].flowStates[flowId] =\n this.config.__flowStateOverrides[flowId]\n\n if (!this.flows.find((flow) => flow.id == flowId)) {\n this.flows.push(\n new Flow({\n config: this.config,\n id: flowId,\n })\n )\n } else {\n this.flows.forEach((flow) => {\n if (flow.id == flowId) {\n flow.resyncState(this.config.__flowStateOverrides[flowId])\n }\n })\n }\n })\n }\n\n /**\n * @ignore\n */\n private async updateConfig(config: FrigadeConfig) {\n this.config = {\n ...this.config,\n ...config,\n }\n if (frigadeGlobalState[getGlobalStateKey(this.config)]) {\n this.getGlobalState().config = this.config\n }\n }\n\n /**\n * @ignore\n */\n private async triggerDeprecatedEventHandlers(\n newState: StatefulFlow,\n previousState?: StatefulFlow\n ) {\n if (newState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousState.flowSlug) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(newState)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n }\n\n /**\n * @ignore\n */\n private triggerEventHandlers(newState: StatefulFlow, previousState?: StatefulFlow) {\n if (newState) {\n for (const flow of this.flows) {\n if (flow.id == newState.flowSlug) {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(newState)\n for (const [event, handlers] of this.eventHandlers.entries()) {\n switch (event) {\n case 'flow.complete':\n if (newState.$state.completed && previousState?.$state.completed === false) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n case 'flow.restart':\n if (!newState.$state.started && previousState?.$state.started === true) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n case 'flow.skip':\n if (newState.$state.skipped && previousState?.$state.skipped === false) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n case 'flow.start':\n if (newState.$state.started && previousState?.$state.started === false) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n case 'step.complete':\n for (const step of newState.data.steps ?? []) {\n if (\n step.$state.completed &&\n !previousState?.data.steps.find(\n (previousStepState) =>\n previousStepState.id === step.id && previousStepState.$state.completed\n )\n ) {\n handlers.forEach((handler) =>\n handler(event, flow, lastFlow, flow.steps.get(step.id))\n )\n }\n }\n break\n case 'step.reset':\n for (const step of newState.data.steps ?? []) {\n const previousStep = previousState?.data.steps.find(\n (previousStepState) => previousStepState.id === step.id\n )\n if (\n step.$state.started == false &&\n !step.$state.lastActionAt &&\n previousStep?.$state.started &&\n previousStep?.$state.lastActionAt\n ) {\n handlers.forEach((handler) =>\n handler(event, flow, lastFlow, flow.steps.get(step.id))\n )\n }\n }\n break\n case 'step.skip':\n for (const step of newState.data.steps ?? []) {\n if (\n step.$state.skipped &&\n !previousState?.data.steps.find(\n (previousStepState) =>\n previousStepState.id === step.id && previousStepState.$state.skipped\n )\n ) {\n handlers.forEach((handler) =>\n handler(event, flow, lastFlow, flow.steps.get(step.id))\n )\n }\n }\n break\n case 'step.start':\n for (const step of newState.data.steps ?? []) {\n if (\n step.$state.started &&\n previousState?.data.steps.find(\n (previousStepState) =>\n previousStepState.id === step.id &&\n previousStepState.$state.started === false\n )\n ) {\n handlers.forEach((handler) =>\n handler(event, flow, lastFlow, flow.steps.get(step.id))\n )\n }\n }\n break\n case 'flow.any':\n if (JSON.stringify(newState) !== JSON.stringify(previousState ?? {})) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n }\n }\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n }\n }\n }\n }\n\n /**\n * @ignore\n */\n async batchRegister(flowIds: CollectionsRegistryBatch) {\n const flowIdsWithWrappedCallbacks = flowIds.map(async ([flowId, callback]) => {\n const currentFlow = await this.getFlow(flowId)\n const wrappedCallback = (visible: boolean) => {\n const prevFlow = this.getGlobalState().previousFlows.get(flowId)\n\n if (prevFlow?.isVisible !== visible) {\n // TODO: Store these in a hash so we can grab this flow's handler and call it\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n handler(currentFlow, prevFlow)\n this.getGlobalState().previousFlows.set(flowId, cloneFlow(currentFlow))\n })\n }\n\n callback?.(visible)\n }\n\n return [flowId, wrappedCallback] as CollectionsRegistryBatch[number]\n })\n\n Promise.all(flowIdsWithWrappedCallbacks).then((results) => {\n this.getGlobalState().collections.batchRegister(results)\n })\n }\n}\n","import type { Flow } from './flow'\n\nexport enum TriggerType {\n MANUAL = 'MANUAL',\n AUTOMATIC = 'AUTOMATIC',\n}\n\nexport enum FlowStatus {\n DRAFT = 'DRAFT',\n ACTIVE = 'ACTIVE',\n ARCHIVED = 'ARCHIVED',\n}\n\nexport type StepAction =\n | 'flow.back'\n | 'flow.complete'\n | 'flow.forward'\n | 'flow.restart'\n | 'flow.skip'\n | 'flow.start'\n | 'step.complete'\n | 'step.skip'\n | 'step.reset'\n | 'step.start'\n | false\n\nexport type FlowChangeEvent =\n | 'flow.any'\n | 'flow.complete'\n | 'flow.restart'\n | 'flow.skip'\n | 'flow.start'\n | 'step.complete'\n | 'step.skip'\n | 'step.reset'\n | 'step.start'\n\nexport type FlowChangeEventHandler = (\n /**\n * The event that triggered the handler.\n */\n event: FlowChangeEvent,\n /**\n * The Flow that triggered the event.\n */\n flow: Flow,\n /**\n * The previous Flow that triggered the event.\n */\n previousFlow?: Flow,\n /**\n * The step that triggered the event. Only applicable for `step.complete`, `step.skip`, `step.reset`, `step.start` events.\n */\n step?: FlowStep\n) => void\n\nexport type PropertyPayload = Record<string, any>\n\nexport interface FlowStep extends StatefulStep {\n /**\n * Order of the step in the Flow.\n */\n order: number\n\n /**\n * Name of the step when shown in a list view.\n */\n stepName?: string\n\n /**\n * Title of the step.\n */\n title?: string\n\n /**\n * Subtitle of the step.\n */\n subtitle?: string\n\n /**\n * Config for the primary button in this step\n */\n primaryButton?: {\n /**\n * Primary button action. (defaults to step.complete)\n */\n action?: StepAction\n\n /**\n * Primary button URI target (defaults to _self).\n */\n target?: string\n\n /**\n * Primary button title. If omitted, the primary button will not be shown.\n */\n title?: string\n\n /**\n * Primary button URI.\n */\n uri?: string\n }\n\n /**\n * @deprecated Use primaryButton.title instead\n * @description Primary button title. If omitted, the primary button will not be shown.\n */\n primaryButtonTitle?: string\n\n /**\n * @deprecated Use primaryButton.uri instead\n * @description Primary button URI.\n */\n primaryButtonUri?: string\n\n /**\n * @deprecated Use primaryButton.target instead\n * @description Primary button URI target (defaults to _self).\n */\n primaryButtonUriTarget?: string\n\n /**\n * Config for the secondary button in this step\n */\n secondaryButton?: {\n /**\n * Secondary button action. (defaults to step.complete)\n */\n action?: StepAction\n\n /**\n * Secondary button URI target (defaults to _self).\n */\n target?: string\n\n /**\n * Secondary button title. If omitted, the secondary button will not be shown.\n */\n title?: string\n\n /**\n * Secondary button URI.\n */\n uri?: string\n }\n\n /**\n * @deprecated Use secondaryButton.title instead\n * @description Secondary button title. If omitted, the secondary button will not be shown.\n */\n secondaryButtonTitle?: string\n\n /**\n * @deprecated Use secondaryButton.uri instead\n * @description Secondary button URI.\n */\n secondaryButtonUri?: string\n\n /**\n * @deprecated Use secondaryButton.target instead\n * @description Secondary button URI target (defaults to _self)\n */\n secondaryButtonUriTarget?: string\n\n /**\n * Text on button if a back button is present.\n */\n backButtonTitle?: string\n\n /**\n * If true, the step will be marked as completed when the secondary button is clicked.\n */\n skippable?: boolean\n\n /**\n * Video url to be shown for components supporting video.\n */\n videoUri?: string\n\n /**\n * Image url to be shown for components supporting image.\n */\n imageUri?: string | null\n\n /**\n * Icon url to be shown for components supporting icons.\n */\n iconUri?: string | null\n\n /**\n * Automatically mark the step as completed when the primary button is clicked. Default is false.\n */\n autoMarkCompleted?: boolean\n\n /**\n * @ignore\n */\n props?: any\n /**\n * Criteria that needs to be met for the step to complete.\n * Completion criteria uses Frigade's [Targeting Engine](https://docs.frigade.com/v2/platform/targeting) to determine if the step should be completed.\n */\n completionCriteria?: string\n\n /**\n * Criteria that needs to be met for the step to start.\n * Start criteria uses Frigade's [Targeting Engine](https://docs.frigade.com/v2/platform/targeting) to determine if the step should be started.\n */\n startCriteria?: string\n\n /**\n * Criteria that needs to be met for the step to be visible.\n * Visibility criteria uses Frigade's [Targeting Engine](https://docs.frigade.com/v2/platform/targeting) to determine if the step should be visible.\n */\n visibilityCriteria?: string\n\n /**\n * Progress if the step is tied to another Frigade Flow through completionCriteria.\n */\n progress?: number\n\n /**\n * Whether the step is dismissible (for instance, tooltips or other non-essential steps).\n */\n dismissible?: boolean\n\n /**\n * Any other additional props defined in the YAML config.\n */\n [x: string | number | symbol]: unknown\n\n /**\n * Marks the step started. This will move the current step index to the given step.\n */\n start: (properties?: PropertyPayload) => Promise<void>\n\n /**\n * Marks the step completed.\n * @param optimistic If true, the step will be marked as completed without waiting for the API and validation of any targeting rules.\n */\n complete: (properties?: PropertyPayload, optimistic?: boolean) => Promise<void>\n\n /**\n * Marks the step skipped. Works similar to step.complete()\n */\n skip: (properties?: PropertyPayload, optimistic?: boolean) => Promise<void>\n\n /**\n * Resets the step (useful for undoing a finished step).\n */\n reset: () => Promise<void>\n\n /**\n * Event handler called when this step's state changes.\n * @deprecated Use `frigade.on('step.complete' | 'step.skip' | 'step.reset' | 'step.start', handler)` instead.\n */\n onStateChange: (callback: (step: FlowStep, previousStep?: FlowStep) => void) => void\n\n /**\n * Removes the given callback from the list of event handlers.\n */\n removeStateChangeHandler: (callback: (step: FlowStep, previousStep?: FlowStep) => void) => void\n\n /**\n * Reference to this step's parent Flow\n */\n flow: Flow\n}\n\nexport interface FrigadeConfig {\n /**\n * Frigade API key. You can find your API key in the Frigade Dashboard under \"Developer\".\n */\n apiKey?: string\n /**\n * API url to use for all requests. Defaults to https://api.frigade.com\n */\n apiUrl?: string\n\n /**\n * User ID to use for all requests. If not provided, a Guest ID will be generated.\n */\n userId?: string\n\n /**\n * Group ID (organization) to use for all requests.\n */\n groupId?: string\n\n /**\n * Optional user properties to send to the API.\n */\n userProperties?: PropertyPayload\n\n /**\n * Optional group properties to send to the API.\n */\n groupProperties?: PropertyPayload\n\n /**\n * Whether to generate a Guest ID and session if no userId is not provided on initialization.\n * If set to false, Frigade will not initialize until a userId is provided via `frigade.identify()`.\n *\n * Defaults to true.\n */\n generateGuestId?: boolean\n\n /**\n * Whether to sync state with Frigade on URL or focus change. Defaults to true.\n */\n syncOnWindowUpdates?: boolean\n\n /**\n * @ignore Internal use only.\n * If enabled, Frigade will not send any data to the API. A user's state will be reset on page refresh.\n */\n __readOnly?: boolean\n\n /**\n * @ignore Internal use only.\n * Map of Flow ID to Flow State for all flows in the app that should be mocked.\n */\n __flowStateOverrides?: Record<string, StatefulFlow>\n\n /**\n * @ignore Internal use only.\n */\n __instanceId?: string\n\n /**\n * @ignore Internal use only.\n */\n __platformVersion?: string\n\n /**\n * @ignore Internal use only.\n */\n __platformName?: string\n\n /**\n * @ignore Internal use only.\n */\n __refreshIntervalInMS: number\n}\n\nexport interface StatefulStep {\n id: string\n /**\n * The state of the step for the given user in the given Flow.\n * Example:\n * ```\n * {\n * completed: true,\n * skipped: false,\n * started: true,\n * visible: true,\n * blocked: false,\n * lastActionAt: \"2014-01-01T23:28:56.782Z\"\n * }\n * ```\n */\n $state: {\n completed: boolean\n skipped: boolean\n started: boolean\n visible: boolean\n blocked: boolean\n lastActionAt?: Date\n }\n // allow any other properties\n [key: string]: any\n}\n\nexport interface StatefulFlow {\n flowSlug: string\n flowName: string\n flowType: FlowType\n version: number\n /**\n * Contains the raw data of the Flow as defined in the YAML config as well as the user's state of each step.\n */\n data: {\n steps: StatefulStep[]\n // allow any other properties\n [key: string]: any\n }\n /**\n * The high-level state of the Flow for the given user.\n */\n $state: {\n currentStepId: string\n currentStepIndex: number\n completed: boolean\n started: boolean\n skipped: boolean\n visible: boolean\n lastActionAt?: Date\n }\n}\n\nexport enum CollectionType {\n CUSTOM = 'CUSTOM',\n DEFAULT = 'DEFAULT',\n}\n\nexport interface ComputedCollection {\n collectionId: string\n flowId: string\n visible: boolean\n allowedComponents: []\n collectionType: CollectionType\n}\n\nexport interface CollectionMetadata {\n computedOrder: ComputedCollection[]\n}\n\nexport interface FlowStates {\n eligibleFlows: StatefulFlow[]\n ineligibleFlows: string[]\n collections?: CollectionMetadata\n}\n\nexport enum FlowType {\n ANNOUNCEMENT = 'ANNOUNCEMENT',\n CHECKLIST = 'CHECKLIST',\n FORM = 'FORM',\n TOUR = 'TOUR',\n SUPPORT = 'SUPPORT',\n CUSTOM = 'CUSTOM',\n BANNER = 'BANNER',\n EMBEDDED_TIP = 'EMBEDDED_TIP',\n NPS_SURVEY = 'NPS_SURVEY',\n SURVEY = 'SURVEY',\n CARD = 'CARD',\n}\n\nexport type FlowActionType =\n | 'STARTED_STEP'\n | 'COMPLETED_STEP'\n | 'SKIPPED_STEP'\n | 'NOT_STARTED_STEP'\n | 'STARTED_FLOW'\n | 'COMPLETED_FLOW'\n | 'SKIPPED_FLOW'\n | 'NOT_STARTED_FLOW'\n\nexport interface FlowStateDTO {\n userId: string\n groupId?: string\n flowSlug?: string\n stepId?: string\n data?: any\n actionType?: FlowActionType\n createdAt?: Date\n context?: FlowStateContext\n}\n\nexport interface FlowStateContext {\n url?: string\n userAgent?: string\n registeredCollectionIds?: string[]\n}\n\nexport interface TrackingEvent {\n event: string\n properties?: PropertyPayload\n}\n\nexport interface SessionDTO {\n userId: string\n groupId?: string\n userProperties?: PropertyPayload\n userEvents?: TrackingEvent[]\n groupProperties?: PropertyPayload\n groupEvents?: TrackingEvent[]\n linkGuestId?: string\n}\n"],"mappings":"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","names":["uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","filteredConfig","_","v","__spreadValues","path","options","__async","getEmptyResponse","gracefulFetch","getHeaders","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","id","visible","overrideStatefulFlow","_a","_b","_c","_d","_e","_f","statefulFlow","clone","step","index","stepObj","existingStep","key","__spreadProps","__spreadValues","newSteps","properties","__async","thisStep","copy","STARTED_STEP","internalComplete","eventType","optimistic","nextStep","isLastStep","isLastIncompleteStep","nextStepIndex","COMPLETED_STEP","SKIPPED_STEP","COMPLETED_FLOW","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","h","STARTED_FLOW","SKIPPED_FLOW","NOT_STARTED_FLOW","currentStep","steps","previousFlow","variables","resyncState","replaceVariables","str","matches","match","variable","applyVariablesToStep","item","e","action","data","stepId","date","flowStatesRaw","getContext","callback","prevFlow","cloneFlow","SDK_VERSION","NOT_STARTED_STEP","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","SKIPPED_STEP","STARTED_STEP","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","LOCAL_STORAGE_PREFIX","REDUNDANT_CALL_MESSAGE","cloneFlow","flow","Flow","clone","obj","getHeaders","config","_a","_b","SDK_VERSION","getLocalStorage","key","isWeb","e","setLocalStorage","value","clearCache","frigadeGlobalState","resetAllLocalStorage","CallQueue","call","response","now","callKey","item","gracefulFetch","url","options","__async","getEmptyResponse","lastCallDataKey","isWebPostRequest","cachedCall","pendingResponse","res","error","body","generateGuestId","guestId","uuidv4","getContext","state","context","__spreadValues","Collections","collectionsData","collectionId","collection","flowId","newCollectionsData","previousCollections","newCollections","newCollection","i","callback","registeredFlow","flowInCollections","item","visibleAPIOverride","flowIdsInThisCollection","otherFlowId","flowIds","visible","_a","Frigade","Fetchable","apiKey","config","__spreadValues","isWeb","event","__async","e","globalStateKey","getGlobalStateKey","frigadeGlobalState","_a","GUEST_PREFIX","userId","properties","__spreadProps","groupId","sessionDTO","lastSessionDTO","flowId","flow","collectionId","collection","enrichedFlows","item","collections","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","that","validator","target","key","value","previousState","newState","Collections","overrideFlowStateRaw","_b","flowStateRaw","getContext","collectionsData","allowedComponents","collectionType","visible","currentCollection","statefulFlow","Flow","_c","_d","handlers","step","previousStepState","previousStep","flowIds","flowIdsWithWrappedCallbacks","_0","callback","currentFlow","prevFlow","results","TriggerType","FlowStatus","FlowType"]}
1
+ {"version":3,"sources":["../src/core/types.ts","../src/shared/utils.ts","../src/shared/state.ts","../src/shared/fetchable.ts","../src/core/flow.ts","../src/version.ts","../src/core/collections.ts","../src/core/frigade.ts"],"sourcesContent":["import type { Flow } from './flow'\n\nexport const DEFAULT_REFRESH_INTERVAL_IN_MS = 100\n\nexport enum TriggerType {\n MANUAL = 'MANUAL',\n AUTOMATIC = 'AUTOMATIC',\n}\n\nexport enum FlowStatus {\n DRAFT = 'DRAFT',\n ACTIVE = 'ACTIVE',\n ARCHIVED = 'ARCHIVED',\n}\n\nexport type StepAction =\n | 'flow.back'\n | 'flow.complete'\n | 'flow.forward'\n | 'flow.restart'\n | 'flow.skip'\n | 'flow.start'\n | 'step.complete'\n | 'step.skip'\n | 'step.reset'\n | 'step.start'\n | false\n\nexport type FlowChangeEvent =\n | 'flow.any'\n | 'flow.complete'\n | 'flow.restart'\n | 'flow.skip'\n | 'flow.start'\n | 'step.complete'\n | 'step.skip'\n | 'step.reset'\n | 'step.start'\n\nexport type FlowChangeEventHandler = (\n /**\n * The event that triggered the handler.\n */\n event: FlowChangeEvent,\n /**\n * The Flow that triggered the event.\n */\n flow: Flow,\n /**\n * The previous Flow that triggered the event.\n */\n previousFlow?: Flow,\n /**\n * The step that triggered the event. Only applicable for `step.complete`, `step.skip`, `step.reset`, `step.start` events.\n */\n step?: FlowStep\n) => void\n\nexport type PropertyPayload = Record<string, any>\n\nexport interface FlowStep extends StatefulStep {\n /**\n * Order of the step in the Flow.\n */\n order: number\n\n /**\n * Name of the step when shown in a list view.\n */\n stepName?: string\n\n /**\n * Title of the step.\n */\n title?: string\n\n /**\n * Subtitle of the step.\n */\n subtitle?: string\n\n /**\n * Config for the primary button in this step\n */\n primaryButton?: {\n /**\n * Primary button action. (defaults to step.complete)\n */\n action?: StepAction\n\n /**\n * Primary button URI target (defaults to _self).\n */\n target?: string\n\n /**\n * Primary button title. If omitted, the primary button will not be shown.\n */\n title?: string\n\n /**\n * Primary button URI.\n */\n uri?: string\n }\n\n /**\n * @deprecated Use primaryButton.title instead\n * @description Primary button title. If omitted, the primary button will not be shown.\n */\n primaryButtonTitle?: string\n\n /**\n * @deprecated Use primaryButton.uri instead\n * @description Primary button URI.\n */\n primaryButtonUri?: string\n\n /**\n * @deprecated Use primaryButton.target instead\n * @description Primary button URI target (defaults to _self).\n */\n primaryButtonUriTarget?: string\n\n /**\n * Config for the secondary button in this step\n */\n secondaryButton?: {\n /**\n * Secondary button action. (defaults to step.complete)\n */\n action?: StepAction\n\n /**\n * Secondary button URI target (defaults to _self).\n */\n target?: string\n\n /**\n * Secondary button title. If omitted, the secondary button will not be shown.\n */\n title?: string\n\n /**\n * Secondary button URI.\n */\n uri?: string\n }\n\n /**\n * @deprecated Use secondaryButton.title instead\n * @description Secondary button title. If omitted, the secondary button will not be shown.\n */\n secondaryButtonTitle?: string\n\n /**\n * @deprecated Use secondaryButton.uri instead\n * @description Secondary button URI.\n */\n secondaryButtonUri?: string\n\n /**\n * @deprecated Use secondaryButton.target instead\n * @description Secondary button URI target (defaults to _self)\n */\n secondaryButtonUriTarget?: string\n\n /**\n * Text on button if a back button is present.\n */\n backButtonTitle?: string\n\n /**\n * If true, the step will be marked as completed when the secondary button is clicked.\n */\n skippable?: boolean\n\n /**\n * Video url to be shown for components supporting video.\n */\n videoUri?: string\n\n /**\n * Image url to be shown for components supporting image.\n */\n imageUri?: string | null\n\n /**\n * Icon url to be shown for components supporting icons.\n */\n iconUri?: string | null\n\n /**\n * Automatically mark the step as completed when the primary button is clicked. Default is false.\n */\n autoMarkCompleted?: boolean\n\n /**\n * @ignore\n */\n props?: any\n /**\n * Criteria that needs to be met for the step to complete.\n * Completion criteria uses Frigade's [Targeting Engine](https://docs.frigade.com/v2/platform/targeting) to determine if the step should be completed.\n */\n completionCriteria?: string\n\n /**\n * Criteria that needs to be met for the step to start.\n * Start criteria uses Frigade's [Targeting Engine](https://docs.frigade.com/v2/platform/targeting) to determine if the step should be started.\n */\n startCriteria?: string\n\n /**\n * Criteria that needs to be met for the step to be visible.\n * Visibility criteria uses Frigade's [Targeting Engine](https://docs.frigade.com/v2/platform/targeting) to determine if the step should be visible.\n */\n visibilityCriteria?: string\n\n /**\n * Progress if the step is tied to another Frigade Flow through completionCriteria.\n */\n progress?: number\n\n /**\n * Whether the step is dismissible (for instance, tooltips or other non-essential steps).\n */\n dismissible?: boolean\n\n /**\n * Any other additional props defined in the YAML config.\n */\n [x: string | number | symbol]: unknown\n\n /**\n * Marks the step started. This will move the current step index to the given step.\n */\n start: (properties?: PropertyPayload) => Promise<void>\n\n /**\n * Marks the step completed.\n * @param optimistic If true, the step will be marked as completed without waiting for the API and validation of any targeting rules.\n */\n complete: (properties?: PropertyPayload, optimistic?: boolean) => Promise<void>\n\n /**\n * Marks the step skipped. Works similar to step.complete()\n */\n skip: (properties?: PropertyPayload, optimistic?: boolean) => Promise<void>\n\n /**\n * Resets the step (useful for undoing a finished step).\n */\n reset: () => Promise<void>\n\n /**\n * Event handler called when this step's state changes.\n * @deprecated Use `frigade.on('step.complete' | 'step.skip' | 'step.reset' | 'step.start', handler)` instead.\n */\n onStateChange: (callback: (step: FlowStep, previousStep?: FlowStep) => void) => void\n\n /**\n * Removes the given callback from the list of event handlers.\n */\n removeStateChangeHandler: (callback: (step: FlowStep, previousStep?: FlowStep) => void) => void\n\n /**\n * Reference to this step's parent Flow\n */\n flow: Flow\n}\n\nexport interface FrigadeConfig {\n /**\n * Frigade API key. You can find your API key in the Frigade Dashboard under \"Developer\".\n */\n apiKey?: string\n /**\n * API url to use for all requests. Defaults to https://api.frigade.com\n */\n apiUrl?: string\n\n /**\n * User ID to use for all requests. If not provided, a Guest ID will be generated.\n */\n userId?: string\n\n /**\n * Group ID (organization) to use for all requests.\n */\n groupId?: string\n\n /**\n * Optional user properties to send to the API.\n */\n userProperties?: PropertyPayload\n\n /**\n * Optional group properties to send to the API.\n */\n groupProperties?: PropertyPayload\n\n /**\n * Whether to generate a Guest ID and session if no userId is not provided on initialization.\n * If set to false, Frigade will not initialize until a userId is provided via `frigade.identify()`.\n *\n * Defaults to true.\n */\n generateGuestId?: boolean\n\n /**\n * Whether to sync state with Frigade on URL or focus change. Defaults to true.\n */\n syncOnWindowUpdates?: boolean\n\n /**\n * @ignore Internal use only.\n * If enabled, Frigade will not send any data to the API. A user's state will be reset on page refresh.\n */\n __readOnly?: boolean\n\n /**\n * @ignore Internal use only.\n * Map of Flow ID to Flow State for all flows in the app that should be mocked.\n */\n __flowStateOverrides?: Record<string, StatefulFlow>\n\n /**\n * @ignore Internal use only.\n */\n __instanceId?: string\n\n /**\n * @ignore Internal use only.\n */\n __platformVersion?: string\n\n /**\n * @ignore Internal use only.\n */\n __platformName?: string\n\n /**\n * @ignore Internal use only.\n */\n __refreshIntervalInMS?: number\n}\n\nexport interface StatefulStep {\n id: string\n /**\n * The state of the step for the given user in the given Flow.\n * Example:\n * ```\n * {\n * completed: true,\n * skipped: false,\n * started: true,\n * visible: true,\n * blocked: false,\n * lastActionAt: \"2014-01-01T23:28:56.782Z\"\n * }\n * ```\n */\n $state: {\n completed: boolean\n skipped: boolean\n started: boolean\n visible: boolean\n blocked: boolean\n lastActionAt?: Date\n }\n // allow any other properties\n [key: string]: any\n}\n\nexport interface StatefulFlow {\n flowSlug: string\n flowName: string\n flowType: FlowType\n version: number\n /**\n * Contains the raw data of the Flow as defined in the YAML config as well as the user's state of each step.\n */\n data: {\n steps: StatefulStep[]\n // allow any other properties\n [key: string]: any\n }\n /**\n * The high-level state of the Flow for the given user.\n */\n $state: {\n currentStepId: string\n currentStepIndex: number\n completed: boolean\n started: boolean\n skipped: boolean\n visible: boolean\n lastActionAt?: Date\n }\n}\n\nexport enum CollectionType {\n CUSTOM = 'CUSTOM',\n DEFAULT = 'DEFAULT',\n}\n\nexport interface ComputedCollection {\n collectionId: string\n flowId: string\n visible: boolean\n allowedComponents: []\n collectionType: CollectionType\n}\n\nexport interface CollectionMetadata {\n computedOrder: ComputedCollection[]\n}\n\nexport interface FlowStates {\n eligibleFlows: StatefulFlow[]\n ineligibleFlows: string[]\n collections?: CollectionMetadata\n}\n\nexport enum FlowType {\n ANNOUNCEMENT = 'ANNOUNCEMENT',\n CHECKLIST = 'CHECKLIST',\n FORM = 'FORM',\n TOUR = 'TOUR',\n SUPPORT = 'SUPPORT',\n CUSTOM = 'CUSTOM',\n BANNER = 'BANNER',\n EMBEDDED_TIP = 'EMBEDDED_TIP',\n NPS_SURVEY = 'NPS_SURVEY',\n SURVEY = 'SURVEY',\n CARD = 'CARD',\n}\n\nexport type FlowActionType =\n | 'STARTED_STEP'\n | 'COMPLETED_STEP'\n | 'SKIPPED_STEP'\n | 'NOT_STARTED_STEP'\n | 'STARTED_FLOW'\n | 'COMPLETED_FLOW'\n | 'SKIPPED_FLOW'\n | 'NOT_STARTED_FLOW'\n\nexport interface FlowStateDTO {\n userId: string\n groupId?: string\n flowSlug?: string\n stepId?: string\n data?: any\n actionType?: FlowActionType\n createdAt?: Date\n context?: FlowStateContext\n}\n\nexport interface FlowStateContext {\n url?: string\n userAgent?: string\n registeredCollectionIds?: string[]\n}\n\nexport interface TrackingEvent {\n event: string\n properties?: PropertyPayload\n}\n\nexport interface SessionDTO {\n userId: string\n groupId?: string\n userProperties?: PropertyPayload\n userEvents?: TrackingEvent[]\n groupProperties?: PropertyPayload\n groupEvents?: TrackingEvent[]\n linkGuestId?: string\n}\n","import { v4 as uuidv4 } from 'uuid'\nimport { Flow } from '../core/flow'\nimport { FrigadeGlobalState, frigadeGlobalState } from './state'\nimport { FlowStateContext, FrigadeConfig } from '../core/types'\nimport { SDK_VERSION } from '../version'\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 SKIPPED_STEP = 'SKIPPED_STEP'\nexport const STARTED_STEP = 'STARTED_STEP'\nconst GUEST_KEY = 'frigade-guest-key'\nexport const GUEST_PREFIX = 'guest_'\nconst GET_CACHE_PREFIX = 'get-cache-'\nconst LOCAL_STORAGE_PREFIX = 'fr-js-'\nconst REDUNDANT_CALL_MESSAGE = 'Redundant call to Frigade API removed'\n\nexport function cloneFlow(flow: Flow): Flow {\n const newFlow = new Flow({\n config: flow.config,\n id: flow.id,\n })\n return newFlow\n}\n\nexport function clone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\nexport function getHeaders(config: FrigadeConfig) {\n return {\n headers: {\n Authorization: `Bearer ${config.apiKey}`,\n 'Content-Type': 'application/json',\n 'x-frigade-sdk-version': config.__platformVersion ?? SDK_VERSION,\n 'x-frigade-sdk-platform': config.__platformName ?? 'Javascript',\n },\n }\n}\n\nfunction getLocalStorage(key: string) {\n if (isWeb()) {\n try {\n return window.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`)\n } catch (e) {\n console.debug('Error getting localStorage:', e)\n return null\n }\n }\n return null\n}\n\nfunction setLocalStorage(key: string, value: string) {\n if (isWeb()) {\n try {\n window.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, value)\n } catch (e) {\n console.debug('Error setting localStorage:', e)\n }\n }\n}\n\nexport function clearCache() {\n Object.keys(frigadeGlobalState).forEach((key) => {\n if (key.startsWith(GET_CACHE_PREFIX)) {\n delete frigadeGlobalState[key]\n }\n })\n}\n\nexport function resetAllLocalStorage() {\n if (isWeb()) {\n // Clear all local storage items that begin with `frigade-`\n Object.keys(window.localStorage).forEach((key) => {\n if (key.startsWith(LOCAL_STORAGE_PREFIX)) {\n window.localStorage.removeItem(key)\n }\n })\n }\n}\n\nclass CallQueue {\n private queue: {\n call: string\n time: number\n response?: Promise<Response>\n }[] = []\n private readonly ttlInMS = 250\n private readonly cacheSize = 10\n\n public push(call: string, response?: Promise<Response>) {\n const now = new Date()\n if (this.queue.length >= this.cacheSize) {\n this.queue.shift()\n }\n this.queue.push({\n call: call,\n time: now.getTime(),\n response: response ?? null,\n })\n }\n\n public hasIdenticalRecentCall(callKey: string) {\n const now = new Date()\n this.queue = this.queue.filter((item) => now.getTime() - item.time < this.ttlInMS)\n return this.queue.find((item) => item.call === callKey)\n }\n\n public hasCall(callKey: string) {\n return this.queue.find((item) => item.call === callKey)\n }\n\n public cancelAllPendingRequests() {\n this.queue = []\n }\n}\n\nglobalThis.callQueue = new CallQueue()\n\nexport async function gracefulFetch(url: string, options: any) {\n if (typeof globalThis.fetch !== 'function') {\n return getEmptyResponse(\n \"- Attempted to call fetch() in an environment that doesn't support it.\"\n )\n }\n\n const lastCallDataKey = `${url}${JSON.stringify(options.body ?? {})}`\n let response\n\n const isWebPostRequest = isWeb() && options && options.body && options.method === 'POST'\n\n if (isWebPostRequest) {\n const cachedCall = globalThis.callQueue.hasIdenticalRecentCall(lastCallDataKey)\n\n if (cachedCall != null && cachedCall.response != null) {\n const cachedResponse = await cachedCall.response\n\n response = cachedResponse.clone()\n }\n }\n\n if (!response) {\n try {\n const pendingResponse = fetch(url, options)\n\n if (isWebPostRequest) {\n globalThis.callQueue.push(\n lastCallDataKey,\n // @ts-ignore\n pendingResponse.then((res) => res.clone()).catch(() => getEmptyResponse())\n )\n }\n\n response = await pendingResponse\n if (isWebPostRequest && !globalThis.callQueue.hasCall(lastCallDataKey)) {\n response = getEmptyResponse(REDUNDANT_CALL_MESSAGE)\n }\n } catch (error) {\n return getEmptyResponse(error)\n }\n }\n\n if (!response) {\n return getEmptyResponse('Received an empty response')\n }\n\n if (response.status >= 400) {\n return getEmptyResponse(response.statusText)\n }\n\n try {\n if (response.status === 204) {\n return getEmptyResponse()\n }\n\n let body\n try {\n body = await response.json()\n } catch (e) {\n return getEmptyResponse()\n }\n\n if (body.error) {\n return getEmptyResponse(body.error)\n }\n\n return body\n } catch (e) {\n return getEmptyResponse(e)\n }\n}\n\nexport function getEmptyResponse(error?: any) {\n if (error) {\n if (error === REDUNDANT_CALL_MESSAGE) {\n console.debug(error)\n } else {\n console.warn('Call to Frigade failed:', error)\n }\n }\n\n // Create empty response that contains the .json method and returns an empty object\n return {\n json: () => ({}),\n clone: () => ({}),\n }\n}\n\nexport function generateGuestId() {\n if (isWeb()) {\n let guestId = getLocalStorage(GUEST_KEY)\n if (!guestId) {\n guestId = `${GUEST_PREFIX}${uuidv4()}`\n setLocalStorage(GUEST_KEY, guestId)\n }\n return guestId\n } else {\n return `${GUEST_PREFIX}${uuidv4()}`\n }\n}\n\nexport function isWeb() {\n return (\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.localStorage !== 'undefined'\n )\n}\n\nexport function getContext(state: FrigadeGlobalState): FlowStateContext {\n let context: FlowStateContext = {\n registeredCollectionIds: Array.from(state.registeredCollectionIds),\n }\n\n if (!isWeb()) {\n return context\n }\n\n return {\n url: state.currentUrl,\n userAgent: navigator.userAgent,\n ...context,\n }\n}\n","import { FlowStates, FlowStep, FrigadeConfig, SessionDTO, StatefulFlow } from '../core/types'\nimport { Flow } from '../core/flow'\nimport type { Collections } from '../core/collections'\n\nexport interface FrigadeGlobalState {\n refreshStateFromAPI: (\n overrideFlowStatesRaw?: FlowStates,\n cancelPendingRequests?: boolean\n ) => Promise<void>\n flowStates: Record<string, StatefulFlow>\n collections: Collections\n registeredCollectionIds: Set<string>\n onFlowStateChangeHandlerWrappers: Map<\n (flow: Flow, previousFlow: Flow) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onStepStateChangeHandlerWrappers: Map<\n (step: FlowStep, previousStep: FlowStep) => void,\n (flow: Flow, previousFlow: Flow) => void\n >\n onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[]\n previousFlows: Map<string, Flow>\n variables: Record<string, Record<string, any>>\n lastFlowSyncDate: Map<string, Date>\n pendingRequests: Map<string, number>\n config: FrigadeConfig\n currentUrl: string\n}\n\nexport let frigadeGlobalState: Record<string, FrigadeGlobalState> = {}\n\nexport function getGlobalStateKey(internalConfig: FrigadeConfig): string {\n return `${internalConfig.__instanceId}-${internalConfig.apiKey}`\n}\n","import { generateGuestId, getEmptyResponse, getHeaders, gracefulFetch } from './utils'\nimport { DEFAULT_REFRESH_INTERVAL_IN_MS, FrigadeConfig } from '../core/types'\nimport { frigadeGlobalState, FrigadeGlobalState, getGlobalStateKey } from './state'\n\nexport class Fetchable {\n public config: FrigadeConfig = {\n apiKey: '',\n apiUrl: 'https://api.frigade.com',\n userId: generateGuestId(),\n __instanceId: Math.random().toString(12).substring(4),\n generateGuestId: true,\n __refreshIntervalInMS: DEFAULT_REFRESH_INTERVAL_IN_MS,\n }\n\n constructor(config: FrigadeConfig) {\n const filteredConfig = Object.fromEntries(Object.entries(config).filter(([_, v]) => v != null))\n this.config = {\n ...this.config,\n ...filteredConfig,\n }\n }\n\n /**\n * @ignore\n */\n public async fetch(path: string, options?: Record<any, any>) {\n if (this.config.__readOnly) {\n return getEmptyResponse()\n }\n\n return gracefulFetch(this.getAPIUrl(path), {\n keepalive: true,\n ...(options ?? {}),\n ...getHeaders(this.config),\n })\n }\n\n private getAPIUrl(path: string) {\n return `${this.config.apiUrl.replace(/\\/$/, '')}/${path.replace(/^\\//, '')}`\n }\n\n /**\n * @ignore\n */\n protected getGlobalState(): FrigadeGlobalState {\n const globalStateKey = getGlobalStateKey(this.config)\n if (!frigadeGlobalState[globalStateKey]) {\n throw new Error('Frigade has not yet been initialized')\n }\n return frigadeGlobalState[globalStateKey]\n }\n}\n","import {\n FlowActionType,\n FlowStateDTO,\n FlowStates,\n FlowStep,\n FlowType,\n FrigadeConfig,\n PropertyPayload,\n StatefulFlow,\n StatefulStep,\n} from './types'\nimport {\n clone,\n cloneFlow,\n COMPLETED_FLOW,\n COMPLETED_STEP,\n getContext,\n NOT_STARTED_FLOW,\n NOT_STARTED_STEP,\n SKIPPED_FLOW,\n SKIPPED_STEP,\n STARTED_FLOW,\n STARTED_STEP,\n} from '../shared/utils'\nimport { Fetchable } from '../shared/fetchable'\nimport { CollectionsRegistryCallback } from './collections'\n\nexport class Flow extends Fetchable {\n /**\n * The Flow's ID.\n */\n public id: string\n /**\n * The version of the Flow.\n */\n public version: number\n /**\n * The Flow's component ID.\n */\n public componentId: string\n /**\n * Ordered map of the Steps in the Flow.\n * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.\n */\n public steps: Map<string, FlowStep>\n /**\n * The user-facing title of the Flow, if defined at the top level of the YAML config.\n */\n public title?: string\n /**\n * The user-facing description of the Flow, if defined at the top level of the YAML config.\n */\n public subtitle?: string\n /**\n * The type of the Flow such as `TOUR` or `CHECKLIST`.\n */\n public type: FlowType\n /**\n * @ignore Internal use only.\n * Props to pass through to the Flow Component in the React SDK.\n */\n public props?: Record<string, unknown> = {}\n /**\n * The raw metadata of the Flow. Contains all properties defined in the Flow's YAML config as well as the current state of the Flow.\n * Generally this should only be used when building custom components to access custom high-level props on the Flow.\n */\n public rawData: StatefulFlow\n /**\n * Whether the Flow is completed or not.\n */\n public isCompleted: boolean\n /**\n * Whether the Flow is started or not.\n */\n public isStarted: boolean\n /**\n * Whether the Flow has been skipped or not.\n */\n public isSkipped: boolean\n /**\n * @ignore\n */\n private _isVisible: boolean = false\n /**\n * Whether the Flow is visible to the user based on the current user/group's state.\n * This function will return `false` if the user has already completed or dismissed the Flow or if the user\n * does not match the Flow's targeting/audience.\n */\n get isVisible() {\n return this._isVisible\n\n // if (this._isVisible === false) {\n // return false\n // }\n\n // return this.getGlobalState().collections.isFlowVisible(this.id)\n }\n set isVisible(visible: boolean) {\n this._isVisible = visible\n }\n\n /**\n * @ignore\n */\n private lastStepUpdate: Map<(step: FlowStep, previousStep: FlowStep) => void, FlowStep> =\n new Map()\n\n constructor({ config, id }: { config: FrigadeConfig; id: string }) {\n super(config)\n this.id = id\n this.init()\n }\n\n /**\n * Reload the Flow data from the server\n */\n reload() {\n this.init()\n }\n\n /**\n * @ignore\n */\n resyncState(overrideStatefulFlow?: StatefulFlow) {\n const statefulFlow = clone(overrideStatefulFlow ?? this.getStatefulFlow())\n\n this.rawData = statefulFlow\n this.title = statefulFlow?.data?.title\n this.subtitle = statefulFlow?.data?.subtitle\n this.type = statefulFlow?.data?.type\n this.props = statefulFlow?.data?.props ?? {}\n this.version = statefulFlow?.version\n this.isCompleted = statefulFlow.$state.completed\n this.isStarted = statefulFlow.$state.started\n this.isSkipped = statefulFlow.$state.skipped\n this._isVisible = statefulFlow.$state.visible\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n const existingStep = this.steps?.get(step.id)\n if (existingStep) {\n Object.keys(stepObj).forEach((key) => {\n existingStep[key] = stepObj[key]\n })\n }\n })\n\n if (this.getGlobalState().variables[this.id]) {\n this.applyVariablesInternal(this.getGlobalState().variables[this.id] ?? {})\n } else {\n this.applyVariablesInternal({})\n }\n }\n\n /**\n * @ignore\n */\n private initStepFromStatefulStep(step: StatefulStep, index: number) {\n return {\n ...step,\n flow: this,\n $state: {\n ...step.$state,\n lastActionAt: step.$state.lastActionAt ? new Date(step.$state.lastActionAt) : undefined,\n },\n order: index,\n } as Partial<FlowStep>\n }\n\n /**\n * @ignore\n */\n private init() {\n const statefulFlow = this.getStatefulFlow()\n const newSteps = new Map<string, FlowStep>()\n\n statefulFlow.data.steps.forEach((step, index) => {\n const stepObj = this.initStepFromStatefulStep(step, index)\n\n stepObj.start = async (properties?: PropertyPayload) => {\n const thisStep = this.steps.get(step.id)\n\n if (this.getCurrentStep().id === thisStep.id && thisStep.$state.started) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n copy.$state.lastActionAt = new Date()\n copy.$state.currentStepId = thisStep.id\n copy.$state.currentStepIndex = thisStep.order\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(STARTED_STEP, properties, thisStep.id)\n }\n\n const internalComplete = async (\n eventType: 'complete' | 'skip',\n properties?: PropertyPayload,\n optimistic: boolean = true\n ) => {\n const thisStep = this.steps.get(step.id)\n\n if ((thisStep.$state.completed || thisStep.$state.skipped) && optimistic) {\n // mark the next step started to advance.\n let nextStep: FlowStep | undefined = this.getStepByIndex(thisStep.order + 1)\n while (nextStep && !nextStep.$state.visible) {\n if (nextStep.order === this.steps.size - 1) {\n break\n }\n nextStep = this.getStepByIndex(nextStep.order + 1)\n }\n if (nextStep) {\n // optimistically mark the next step as started\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.currentStepId = this.getStepByIndex(thisStep.order + 1).id\n copy.$state.currentStepIndex = thisStep.order + 1\n // mark the next step as started\n copy.data.steps[thisStep.order + 1].$state.started = true\n\n this.getGlobalState().flowStates[this.id] = copy\n\n await this.sendFlowStateToAPI(STARTED_STEP, undefined, nextStep.id)\n\n this.resyncState()\n }\n\n return\n }\n\n const isLastStep = this.getCurrentStepOrder() + 1 === this.getNumberOfAvailableSteps()\n const isLastIncompleteStep =\n Array.from(this.steps.values()).filter(\n (step) => step.$state.visible && !step.$state.completed && !step.$state.skipped\n ).length === 1 && isLastStep\n\n if (optimistic) {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n\n copy.$state.started = true\n if (eventType == 'complete') {\n copy.data.steps[thisStep.order].$state.completed = true\n } else {\n copy.data.steps[thisStep.order].$state.skipped = true\n }\n copy.data.steps[thisStep.order].$state.started = true\n copy.data.steps[thisStep.order].$state.lastActionAt = new Date()\n\n if (!isLastStep) {\n const nextStepIndex = this.getNextVisibleStepIndexAfterIndex(thisStep.order)\n if (nextStepIndex !== -1) {\n copy.$state.currentStepId = this.getStepByIndex(nextStepIndex).id\n copy.$state.currentStepIndex = nextStepIndex\n copy.data.steps[nextStepIndex].$state.started = true\n }\n }\n if (isLastIncompleteStep) {\n copy.$state.completed = true\n copy.$state.visible = false\n }\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n if (isLastIncompleteStep) {\n this.optimisticallyMarkFlowCompleted()\n }\n }\n\n await this.sendFlowStateToAPI(\n eventType == 'complete' ? COMPLETED_STEP : SKIPPED_STEP,\n properties,\n thisStep.id\n )\n if (isLastIncompleteStep) {\n await this.sendFlowStateToAPI(COMPLETED_FLOW, properties)\n }\n }\n\n stepObj.complete = async (properties?: PropertyPayload, optimistic: boolean = true) => {\n await internalComplete('complete', properties, optimistic)\n }\n\n stepObj.skip = async (properties?: PropertyPayload, optimistic: boolean = true) => {\n await internalComplete('skip', properties, optimistic)\n }\n\n stepObj.reset = async () => {\n const thisStep = this.steps.get(step.id)\n\n if (!thisStep.$state.completed) {\n return\n }\n\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.data.steps[thisStep.order].$state.started = false\n copy.data.steps[thisStep.order].$state.completed = false\n copy.data.steps[thisStep.order].$state.lastActionAt = undefined\n\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n\n await this.sendFlowStateToAPI(NOT_STARTED_STEP, undefined, thisStep.id)\n }\n\n stepObj.onStateChange = (handler: (step: FlowStep, previousStep: FlowStep) => void) => {\n const wrapperHandler = (flow: Flow) => {\n if (flow.id !== this.id) {\n return\n }\n const thisStep = flow.steps.get(step.id)\n const previousStep = this.lastStepUpdate.get(handler)\n\n if (\n thisStep.$state.completed !== previousStep?.$state.completed ||\n thisStep.$state.started !== previousStep?.$state.started ||\n thisStep.$state.visible !== previousStep?.$state.visible ||\n thisStep.$state.blocked !== previousStep?.$state.blocked\n ) {\n handler(thisStep, previousStep ?? clone(thisStep))\n this.lastStepUpdate.set(handler, clone(thisStep))\n }\n }\n this.getGlobalState().onStepStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n stepObj.removeStateChangeHandler = (\n handler: (step: FlowStep, previousStep: FlowStep) => void\n ) => {\n const wrapperHandler = this.getGlobalState().onStepStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n newSteps.set(step.id, stepObj as FlowStep)\n })\n this.steps = newSteps\n\n this.resyncState()\n }\n\n /**\n * Marks the flow started\n */\n public async start(properties?: PropertyPayload) {\n if (this.isStarted || this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowStarted()\n\n await this.sendFlowStateToAPI(STARTED_FLOW, properties)\n }\n\n /**\n * Marks the flow completed\n */\n public async complete(properties?: PropertyPayload) {\n if (this.isCompleted) {\n return\n }\n this.optimisticallyMarkFlowCompleted()\n await this.sendFlowStateToAPI(COMPLETED_FLOW, properties)\n }\n\n /**\n * Marks the flow skipped\n */\n public async skip(properties?: PropertyPayload) {\n if (this.isSkipped) {\n return\n }\n this.optimisticallyMarkFlowSkipped()\n await this.sendFlowStateToAPI(SKIPPED_FLOW, properties)\n }\n\n /**\n * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async forward(properties?: PropertyPayload) {\n const nextStep = this.getStepByIndex(\n this.getNextVisibleStepIndexAfterIndex(this.getCurrentStepIndex())\n )\n\n if (nextStep) {\n await nextStep.start(properties)\n }\n }\n\n /**\n * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.\n */\n public async back(properties?: PropertyPayload) {\n // Continue back until a visible step is found\n let previousStep = this.getStepByIndex(this.getCurrentStepIndex() - 1)\n while (previousStep && !previousStep.$state.visible) {\n if (previousStep.order === 0) {\n break\n }\n previousStep = this.getStepByIndex(previousStep.order - 1)\n }\n\n if (previousStep) {\n await previousStep.start(properties)\n }\n }\n\n /**\n * Restarts the flow/marks it not started\n */\n public async restart() {\n await this.sendFlowStateToAPI(NOT_STARTED_FLOW)\n }\n\n /**\n * Get a step by index\n * @param index\n */\n public getStepByIndex(index: number): FlowStep | undefined {\n return this.steps.get(Array.from(this.steps.keys())[index])\n }\n\n /**\n * Gets current step. If the current step is not visible, it will return the first visible step after it.\n * If no steps are visible, it will return undefined.\n */\n public getCurrentStep(): FlowStep | undefined {\n let currentStep = this.steps.get(this.getStatefulFlow().$state.currentStepId)\n if (currentStep) {\n return currentStep\n }\n currentStep = this.getFirstVisibleStep()\n\n return currentStep\n }\n\n /**\n * @ignore\n */\n private getFirstVisibleStep() {\n return this.getStepByIndex(this.getNextVisibleStepIndexAfterIndex(-1))\n }\n\n /**\n * @ignore\n */\n private getNextVisibleStepIndexAfterIndex(index: number): number {\n const steps = Array.from(this.steps.values())\n for (let i = index + 1; i < steps.length; i++) {\n if (steps[i].$state.visible) {\n return i\n }\n }\n return -1\n }\n\n /**\n * Get the index of the current step. Starts at 0\n */\n public getCurrentStepIndex(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.keys()).indexOf(currentStep.id)\n }\n\n /**\n * Get the number of completed steps for the current user in the current flow\n */\n public getNumberOfCompletedSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.completed).length\n }\n\n /**\n * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.\n */\n public getNumberOfAvailableSteps(): number {\n return Array.from(this.steps.values()).filter((step) => step.$state.visible).length\n }\n\n /**\n * Returns the current step's order based on the number of available steps.\n * Works similar to getCurrentStepIndex but takes into account hidden steps due to visibilityCriteria.\n */\n public getCurrentStepOrder(): number {\n const currentStep = this.getCurrentStep()\n return Array.from(this.steps.values())\n .filter((step) => step.$state.visible)\n .indexOf(currentStep)\n }\n\n /**\n * Get the progress of the flow as a number between 0 and 1. Useful when rendering a progress bar.\n */\n public getProgress(): number {\n return (this.getNumberOfCompletedSteps() || 0) / (this.getNumberOfAvailableSteps() || 1)\n }\n\n /**\n * @ignore\n * @deprecated Use `frigade.on('flow.complete' | 'flow.skip' | 'flow.restart' | 'flow.start', handler)` instead.\n */\n public onStateChange(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = (flow: Flow, previousFlow: Flow) => {\n if (flow.id === this.id) {\n if (\n flow.isCompleted !== previousFlow?.isCompleted ||\n flow.isStarted !== previousFlow?.isStarted ||\n flow.isSkipped !== previousFlow?.isSkipped ||\n flow.isVisible !== previousFlow?.isVisible ||\n JSON.stringify(flow.steps) !== JSON.stringify(previousFlow?.steps)\n ) {\n handler(flow, previousFlow)\n }\n }\n }\n this.getGlobalState().onFlowStateChangeHandlerWrappers.set(handler, wrapperHandler)\n this.getGlobalState().onFlowStateChangeHandlers.push(wrapperHandler)\n }\n\n /**\n * @ignore\n */\n public removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void) {\n const wrapperHandler = this.getGlobalState().onFlowStateChangeHandlerWrappers.get(handler)\n if (wrapperHandler) {\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== wrapperHandler)\n }\n }\n\n /**\n * Apply variables to the flow. This will replace any `${variable}` in the title, subtitle, and step fields with the value of the variable.\n * @param variables A record of variables to apply to the flow.\n */\n public applyVariables(variables: Record<string, any>) {\n this.applyVariablesInternal(variables, true)\n }\n\n /**\n * @ignore\n */\n private applyVariablesInternal(variables: Record<string, any>, resyncState: boolean = false) {\n // Replace ${variable} with the value of the variable\n const replaceVariables = (str: string) => {\n const matches = str.match(/\\${(.*?)}/g)\n if (matches) {\n matches.forEach((match) => {\n const variable = match.replace('${', '').replace('}', '')\n if (!variables[variable]) {\n // set the variable to blank string as it was not found\n str = str.replace(match, '')\n return\n }\n str = str.replace(match, variables[variable])\n })\n }\n return str\n }\n\n this.title = replaceVariables(this.title ?? '')\n this.subtitle = replaceVariables(this.subtitle ?? '')\n const applyVariablesToStep = (step: any) => {\n if (!step) {\n return\n }\n\n Object.keys(step).forEach((key) => {\n if (typeof step[key] === 'string') {\n // @ts-ignore\n step[key] = replaceVariables(step[key])\n } else if (typeof step[key] === 'object') {\n applyVariablesToStep(step[key])\n } else if (Array.isArray(step[key])) {\n step[key].forEach((item: any) => {\n applyVariablesToStep(item)\n })\n }\n })\n }\n\n if (this.steps) {\n this.steps.forEach((step) => {\n try {\n console\n applyVariablesToStep(step)\n } catch (e) {\n // ignore any failures\n }\n })\n }\n\n this.getGlobalState().variables[this.id] = {\n ...this.getGlobalState().variables[this.id],\n ...variables,\n }\n\n if (resyncState) {\n this.resyncState()\n }\n }\n\n /**\n * @ignore\n */\n private getStatefulFlow(): StatefulFlow {\n const userFlowStates = this.getGlobalState().flowStates\n return userFlowStates[this.id]\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowCompleted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.completed = true\n copy.$state.started = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowStarted() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.started = true\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n private async sendFlowStateToAPI(\n action: FlowActionType,\n data?: PropertyPayload,\n stepId?: string\n ) {\n const date = new Date()\n this.getGlobalState().lastFlowSyncDate[this.id] = date\n this.getGlobalState().pendingRequests[this.id] =\n (this.getGlobalState().pendingRequests[this.id] ?? 0) + 1\n const flowStatesRaw: FlowStates = await this.fetch('/v1/public/flowStates', {\n method: 'POST',\n body: JSON.stringify({\n userId: this.getGlobalState().config.userId,\n groupId: this.getGlobalState().config.groupId,\n flowSlug: this.id,\n stepId: stepId,\n data: data ? data : {},\n actionType: action,\n createdAt: date,\n context: getContext(this.getGlobalState()),\n } as FlowStateDTO),\n })\n this.getGlobalState().pendingRequests[this.id] -= 1\n // if a newer request was sent, use that one.\n // except if there are other pending requests\n if (\n date < this.getGlobalState().lastFlowSyncDate[this.id] ||\n this.getGlobalState().pendingRequests[this.id] > 0\n ) {\n return\n }\n await this.getGlobalState().refreshStateFromAPI(flowStatesRaw)\n }\n\n /**\n * @ignore\n */\n private optimisticallyMarkFlowSkipped() {\n const copy = clone(this.getGlobalState().flowStates[this.id])\n copy.$state.skipped = true\n copy.$state.visible = false\n this.getGlobalState().flowStates[this.id] = copy\n this.resyncState()\n }\n\n public register(callback?: CollectionsRegistryCallback) {\n const globalState = this.getGlobalState()\n\n globalState.collections.register(this.id, (visible) => {\n const prevFlow = this.getGlobalState().previousFlows.get(this.id)\n\n if (prevFlow?._isVisible !== visible) {\n // TODO: Store these in a hash so we can grab this flow's handler and call it\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n handler(this, prevFlow)\n this.getGlobalState().previousFlows.set(this.id, cloneFlow(this))\n })\n }\n\n callback?.(visible)\n })\n }\n\n public unregister() {\n if (!this.getGlobalState().collections) {\n return\n }\n this.getGlobalState().collections.unregister(this.id)\n }\n}\n","export const SDK_VERSION = '0.9.1';","import type { Flow } from './flow'\n\nexport type CollectionsRegistryCallback = (visible: boolean) => void\n\nexport type CollectionsRegistryBatch = [string, CollectionsRegistryCallback][]\n\nexport interface CollectionsRegistryItem {\n visible: boolean\n visited: boolean\n callback: CollectionsRegistryCallback\n}\n\nexport interface Collection {\n allowedComponents: string[]\n collectionType: 'DEFAULT' | 'CUSTOM'\n flows: {\n flowId: string\n visible: boolean\n }[]\n}\n\nexport interface EnrichedCollection extends Omit<Collection, 'flows'> {\n flows: Array<\n Collection['flows'][number] & {\n flow: Flow\n }\n >\n}\n\nexport type CollectionsList = Map<string, Collection>\n\nexport class Collections {\n private readonly registry: Map<string, CollectionsRegistryItem> = new Map()\n private registryStateLocked: boolean = false\n private collections: CollectionsList = new Map()\n private flowsInCollections: Set<string> = new Set()\n private hasChanges: boolean = false\n\n constructor(collectionsData: CollectionsList) {\n this.ingestCollectionsData(collectionsData)\n }\n\n getCollection(collectionId: string) {\n return this.collections.get(collectionId)\n }\n\n getCollections() {\n return this.collections\n }\n\n collectionsHaveChanged() {\n return this.hasChanges\n }\n\n ingestCollectionsData(collectionsData: CollectionsList) {\n this.hasChanges = true\n\n this.checkIfCollectionsHaveChanged(collectionsData)\n\n if (!this.hasChanges) {\n return\n }\n\n this.collections = collectionsData\n\n for (const [, collection] of this.collections) {\n for (const { flowId } of collection.flows) {\n this.flowsInCollections.add(flowId)\n }\n }\n\n if (this.registry.size > 0) {\n if (!this.registryStateLocked) {\n this.resetRegistryState()\n }\n\n this.processCollections()\n }\n\n this.fireCallbacks()\n }\n\n private checkIfCollectionsHaveChanged(newCollectionsData: CollectionsList) {\n const previousCollections = this.collections\n const newCollections = newCollectionsData\n\n if (previousCollections.size !== newCollections.size) {\n this.hasChanges = true\n }\n\n for (const [collectionId, collection] of previousCollections) {\n const newCollection = newCollections.get(collectionId)\n if (collection.flows.length !== newCollection.flows.length) {\n this.hasChanges = true\n break\n }\n\n for (let i = 0; i < collection.flows.length; i++) {\n if (\n collection.flows[i].flowId !== newCollection.flows[i].flowId ||\n collection.flows[i].visible !== newCollection.flows[i].visible\n ) {\n this.hasChanges = true\n break\n }\n }\n }\n }\n\n fireCallbacks() {\n for (const [flowId, { callback }] of this.registry) {\n if (typeof callback === 'function') {\n callback(this.isFlowVisible(flowId))\n }\n }\n }\n\n isFlowVisible(flowId: string) {\n const registeredFlow = this.registry.get(flowId)\n const flowInCollections = this.flowsInCollections.has(flowId)\n\n if (registeredFlow == null || !flowInCollections) {\n return true\n }\n\n return registeredFlow.visible\n }\n\n lockRegistryState() {\n this.registryStateLocked = true\n }\n\n unlockRegistryState() {\n this.registryStateLocked = false\n }\n\n resetRegistryState() {\n for (const [flowId, item] of this.registry) {\n item.visible = false\n item.visited = false\n\n this.registry.set(flowId, item)\n }\n }\n\n processCollections() {\n for (const [, collection] of this.collections) {\n for (const { flowId, visible: visibleAPIOverride } of collection.flows) {\n const registeredFlow = this.registry.get(flowId)\n\n // If this flow in the collection isn't registered, we have no opinion on it yet\n if (registeredFlow == null) {\n continue\n }\n\n // The API can force a flow to be hidden due to cool-offs, etc.\n if (visibleAPIOverride === false && registeredFlow.visible !== true) {\n this.visit(flowId, false)\n continue\n }\n\n // If this flow was processed in a previous collection and the registry is locked,\n // visibility shouldn't change until next time we run processCollections\n if (registeredFlow.visited && this.registryStateLocked) {\n continue\n }\n\n const flowIdsInThisCollection = collection.flows\n .map(({ flowId: otherFlowId }) => otherFlowId)\n .filter((otherFlowId) => otherFlowId !== flowId)\n\n // If another flow in this collection has been visited already and is visible...\n // const anotherFlowInThisCollectionIsVisible = flowIdsInThisCollection.some((otherId) => {\n // const { visible: otherVisible, visited: otherVisited } = this.registry.get(otherId) ?? {}\n\n // return otherVisible && otherVisited\n // })\n\n // ...then this flow is hidden\n // if (anotherFlowInThisCollectionIsVisible) {\n // this.visit(flowId, false)\n\n // continue\n // }\n\n // No other flows are visible, so this flow is visible by default\n this.visit(flowId)\n }\n }\n }\n\n register(flowId: string | CollectionsRegistryBatch, callback?: CollectionsRegistryCallback) {\n if (Array.isArray(flowId)) {\n this.batchRegister(flowId)\n return\n }\n\n this.registry.set(flowId, {\n callback: callback ?? (() => {}),\n visible: false,\n visited: false,\n })\n\n if (!this.registryStateLocked) {\n this.resetRegistryState()\n }\n\n this.processCollections()\n\n this.fireCallbacks()\n }\n\n batchRegister(flowIds: CollectionsRegistryBatch) {\n flowIds.forEach(([flowId, callback]) => {\n this.registry.set(flowId, {\n callback: callback ?? (() => {}),\n visible: false,\n visited: false,\n })\n })\n\n if (!this.registryStateLocked) {\n this.resetRegistryState()\n }\n\n this.processCollections()\n\n this.lockRegistryState()\n\n this.fireCallbacks()\n }\n\n unregister(flowId: string) {\n this.registry.delete(flowId)\n\n this.resetRegistryState()\n this.processCollections()\n\n this.fireCallbacks()\n }\n\n private visit(flowId: string, visible: boolean = true) {\n const item = this.registry.get(flowId) ?? {\n callback: () => {},\n visible,\n visited: true,\n }\n\n item.visible = visible\n item.visited = true\n\n this.registry.set(flowId, item)\n }\n}\n","import {\n DEFAULT_REFRESH_INTERVAL_IN_MS,\n FlowChangeEvent,\n FlowChangeEventHandler,\n FlowStateDTO,\n FlowStates,\n FlowStep,\n FrigadeConfig,\n PropertyPayload,\n SessionDTO,\n StatefulFlow,\n} from './types'\nimport {\n clearCache,\n cloneFlow,\n getContext,\n GUEST_PREFIX,\n isWeb,\n resetAllLocalStorage,\n} from '../shared/utils'\nimport { Flow } from './flow'\nimport { frigadeGlobalState, getGlobalStateKey } from '../shared/state'\nimport { Fetchable } from '../shared/fetchable'\nimport {\n type Collection,\n Collections,\n type CollectionsList,\n type CollectionsRegistryBatch,\n type EnrichedCollection,\n} from './collections'\n\nexport class Frigade extends Fetchable {\n /**\n * @ignore\n */\n private flows: Flow[] = []\n /**\n * @ignore\n */\n private initPromise: Promise<void>\n /**\n * @ignore\n */\n private hasFailed = false\n /**\n * @ignore\n */\n private lastSessionDTO?: SessionDTO\n /**\n * @ignore\n */\n private eventHandlers: Map<FlowChangeEvent, FlowChangeEventHandler[]> = new Map()\n /**\n * @ignore\n */\n private refreshTimeout: ReturnType<typeof setTimeout> | null = null\n /**\n * @ignore\n */\n private queuedRefresh: boolean = false\n\n /**\n * @ignore\n */\n private visibilityChangeHandler = () => {\n if (document.visibilityState === 'visible') {\n this.queueRefreshStateFromAPI()\n }\n }\n\n /**\n * @ignore\n */\n private queueRefreshStateFromAPI() {\n this.queuedRefresh = true\n if (this.refreshTimeout) {\n return\n }\n\n this.refreshTimeout = setTimeout(async () => {\n if (this.queuedRefresh) {\n this.getGlobalState().currentUrl = window.location.href\n await this.refreshStateFromAPI()\n this.queuedRefresh = false\n }\n this.refreshTimeout = null\n }, this.getGlobalState().config.__refreshIntervalInMS ?? DEFAULT_REFRESH_INTERVAL_IN_MS)\n }\n\n constructor(apiKey: string, config?: FrigadeConfig) {\n super({\n apiKey,\n ...config,\n })\n this.init(this.config)\n if (isWeb() && this.config.syncOnWindowUpdates !== false) {\n document.addEventListener('visibilitychange', this.visibilityChangeHandler)\n // @ts-ignore\n if (window.navigation) {\n // @ts-ignore\n window.navigation.addEventListener('navigate', async (event) => {\n try {\n if (this.getGlobalState().currentUrl === event.destination.url) {\n return\n }\n // if the new base url is the same but with a hashtag, don't refresh the state as the page has not changed.\n if (\n event.destination.url &&\n this.getGlobalState().currentUrl &&\n event.destination.url.split('#')[0] === this.getGlobalState().currentUrl.split('#')[0]\n ) {\n return\n }\n this.queueRefreshStateFromAPI()\n } catch (e) {}\n })\n }\n }\n }\n\n /**\n * Gets the current configuration.\n * See [FrigadeConfig](https://github.com/FrigadeHQ/javascript/blob/main/packages/js-api/src/core/types.ts#L240) for a list of available options.\n */\n getConfig() {\n return this.config\n }\n\n /**\n * @ignore\n */\n destroy() {\n if (isWeb()) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler)\n // Remove all other event listeners\n const globalStateKey = getGlobalStateKey(this.config)\n if (frigadeGlobalState[globalStateKey]) {\n frigadeGlobalState[globalStateKey].onFlowStateChangeHandlers = []\n }\n }\n }\n\n /**\n * @ignore\n */\n private async init(config: FrigadeConfig): Promise<void> {\n this.updateConfig({\n ...this.config,\n ...config,\n })\n\n if (!this.config.userId) {\n return\n }\n\n this.initPromise = (async () => {\n if (!this.config.__readOnly) {\n if (this.config.userId?.startsWith(GUEST_PREFIX)) {\n // do nothing\n } else if (this.config.userId && this.config.groupId) {\n await this.session({\n userId: this.config.userId,\n groupId: this.config.groupId,\n userProperties: this.config.userProperties,\n groupProperties: this.config.groupProperties,\n })\n } else if (this.config.userId) {\n await this.session({\n userId: this.config.userId,\n userProperties: this.config.userProperties,\n })\n }\n }\n await this.refreshStateFromAPI()\n })()\n\n return this.initPromise\n }\n\n /**\n * Set the current user.\n * @param userId\n * @param properties\n */\n public async identify(userId: string, properties?: PropertyPayload): Promise<void> {\n if (userId !== this.config.userId) {\n await this.updateConfig({ ...this.config, userId })\n await this.reload()\n }\n\n await this.initIfNeeded()\n const isNewSession = await this.session({\n userId: this.config.userId,\n userProperties: properties,\n })\n if (isNewSession) {\n await this.resync()\n }\n }\n\n /**\n * Set the group for the current user.\n * @param groupId\n * @param properties\n */\n public async group(groupId?: string, properties?: PropertyPayload): Promise<void> {\n await this.initIfNeeded()\n this.updateConfig({ ...this.config, groupId })\n await this.session({\n userId: this.config.userId,\n groupId: this.config.groupId,\n groupProperties: properties,\n })\n await this.resync()\n }\n\n /**\n * Track an event for the current user (and group if set).\n * @param event\n * @param properties\n */\n public async track(event: string, properties?: PropertyPayload): Promise<void> {\n await this.initIfNeeded()\n if (!event) {\n console.error('Event name is required to track an event')\n return\n }\n if (this.config.userId && this.config.groupId) {\n await this.session({\n userId: this.config.userId,\n groupId: this.config.groupId,\n groupEvents: [\n {\n event,\n properties,\n },\n ],\n userEvents: [\n {\n event,\n properties,\n },\n ],\n })\n } else if (this.config.userId) {\n await this.session({\n userId: this.config.userId,\n userEvents: [\n {\n event,\n properties,\n },\n ],\n })\n }\n await this.resync()\n }\n\n /**\n * @ignore\n */\n private async session(sessionDTO: SessionDTO) {\n const lastSessionDTO = this.lastSessionDTO\n\n if (lastSessionDTO && JSON.stringify(lastSessionDTO) === JSON.stringify(sessionDTO)) {\n return false\n }\n\n await this.fetch('/v1/public/sessions', {\n method: 'POST',\n body: JSON.stringify(sessionDTO),\n })\n\n this.lastSessionDTO = sessionDTO\n\n return true\n }\n\n /**\n * @ignore\n */\n public isReady(): boolean {\n return Boolean(this.config.__instanceId && this.config.apiKey && this.initPromise)\n }\n\n /**\n * Get a Flow by its ID.\n * @param flowId\n */\n public async getFlow(flowId: string) {\n if (\n this.getConfig().generateGuestId === false &&\n this.getConfig().userId &&\n this.getConfig().userId.startsWith(GUEST_PREFIX)\n ) {\n return undefined\n }\n await this.initIfNeeded()\n\n return this.getFlowSync(flowId)\n }\n\n /**\n * @ignore\n */\n public getFlowSync(flowId: string) {\n return this.flows.find((flow) => flow.id == flowId)\n }\n\n public async getFlows() {\n await this.initIfNeeded()\n if (\n this.config.generateGuestId === false &&\n this.getConfig().userId?.startsWith(GUEST_PREFIX)\n ) {\n return []\n }\n return this.flows\n }\n\n public async getCollection(collectionId: string) {\n await this.initIfNeeded()\n const collection = this.getGlobalState().collections.getCollection(collectionId)\n\n if (collection == null) {\n return undefined\n }\n\n this.registerCollection(collectionId)\n\n const enrichedFlows = await Promise.all(\n collection.flows.map(async (item) => ({\n ...item,\n flow: await this.getFlow(item.flowId),\n }))\n )\n\n collection.flows = enrichedFlows\n\n return collection as EnrichedCollection\n }\n\n public async registerCollection(collectionId: string) {\n await this.initIfNeeded()\n if (collectionId) {\n this.getGlobalState().registeredCollectionIds.add(collectionId)\n }\n }\n\n /**\n * @ignore\n */\n public getCollectionSync(collectionId: string): Collection | undefined {\n const collection = this.getGlobalState().collections.getCollection(collectionId)\n\n if (collection == null) {\n return undefined\n }\n\n this.getGlobalState().registeredCollectionIds.add(collectionId)\n\n return collection\n }\n\n /**\n * @ignore\n */\n public getCollectionsSync(): CollectionsList | undefined {\n return this.getGlobalState().collections.getCollections()\n }\n\n public async getCollections(): Promise<CollectionsList | undefined> {\n await this.initIfNeeded()\n\n if (!this.config.userId && this.config.generateGuestId === false) {\n return undefined\n }\n\n const collections = this.getGlobalState().collections.getCollections()\n\n if (collections == null) {\n return undefined\n }\n\n return collections\n }\n\n /**\n * Reload the current state of the flows by calling the Frigade API.\n * This will trigger all event handlers.\n * @param config optional config to use when reloading. If not passed, the current config will be used.\n */\n public async reload(config?: FrigadeConfig) {\n resetAllLocalStorage()\n clearCache()\n if (config) {\n await this.updateConfig(config)\n this.mockFlowStates(getGlobalStateKey(this.config))\n }\n this.initPromise = null\n await this.init(this.config)\n this.triggerAllLegacyEventHandlers()\n this.triggerAllEventHandlers()\n }\n\n /**\n * @ignore\n */\n private triggerAllLegacyEventHandlers() {\n this.flows.forEach((flow) => {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n })\n }\n\n private triggerAllEventHandlers() {\n this.flows.forEach((flow) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n this.triggerEventHandlers(flow.rawData, lastFlow?.rawData)\n })\n }\n\n private async resync() {\n await this.refreshStateFromAPI()\n }\n\n /**\n * Event handler that captures all changes that happen to the state of the Flows.\n * @deprecated Use `frigade.on` instead.\n * @param handler\n */\n public async onStateChange(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers.push(handler)\n }\n\n /**\n * Event handler that captures all changes that happen to the state of the Flows. Use `flow.any` to capture all events.\n * @param event `flow.any` | `flow.complete` | `flow.restart` | `flow.skip` | `flow.start` | `step.complete` | `step.skip` | `step.reset` | `step.start`\n * @param handler\n */\n public async on(event: FlowChangeEvent, handler: FlowChangeEventHandler) {\n this.eventHandlers.set(event, [...(this.eventHandlers.get(event) ?? []), handler])\n }\n\n /**\n * Removes the given handler.\n * @param event `flow.any` | `flow.complete` | `flow.restart` | `flow.skip` | `flow.start` | `step.complete` | `step.skip` | `step.reset` | `step.start`\n * @param handler\n */\n public async off(event: FlowChangeEvent, handler: FlowChangeEventHandler) {\n this.eventHandlers.set(\n event,\n (this.eventHandlers.get(event) ?? []).filter((h) => h !== handler)\n )\n }\n\n /**\n * Returns true if the JS SDK failed to connect to the Frigade API.\n */\n hasFailedToLoad() {\n return this.hasFailed\n }\n\n /**\n * Removes the given handler from the list of event handlers.\n * @param handler\n */\n public async removeStateChangeHandler(handler: (flow: Flow, previousFlow?: Flow) => void) {\n await this.initIfNeeded()\n this.getGlobalState().onFlowStateChangeHandlers =\n this.getGlobalState().onFlowStateChangeHandlers.filter((h) => h !== handler)\n }\n\n /**\n * @ignore\n */\n private async initIfNeeded() {\n if (this.initPromise) {\n return this.initPromise\n } else {\n return this.init(this.config)\n }\n }\n\n /**\n * @ignore\n */\n private async refreshStateFromAPI(): Promise<void> {\n const globalStateKey = getGlobalStateKey(this.config)\n\n if (!frigadeGlobalState[globalStateKey]) {\n const that = this\n\n let validator = {\n set: function (target: any, key: any, value: any) {\n if (target[key]) {\n const previousState = target[key] as StatefulFlow\n const newState = value as StatefulFlow\n if (JSON.stringify(previousState) !== JSON.stringify(newState)) {\n that.triggerDeprecatedEventHandlers(newState, previousState)\n that.triggerEventHandlers(newState, previousState)\n }\n }\n\n target[key] = value\n return true\n },\n }\n\n frigadeGlobalState[globalStateKey] = {\n refreshStateFromAPI: async () => {},\n collections: new Collections(new Map()),\n registeredCollectionIds: new Set(),\n flowStates: new Proxy({}, validator),\n onFlowStateChangeHandlerWrappers: new Map(),\n onStepStateChangeHandlerWrappers: new Map(),\n onFlowStateChangeHandlers: [],\n previousFlows: new Map(),\n variables: {},\n config: this.config,\n currentUrl: isWeb() ? window.location.href : '',\n pendingRequests: new Map(),\n lastFlowSyncDate: new Map(),\n }\n\n if (this.config.__readOnly && this.config.__flowStateOverrides) {\n this.mockFlowStates(globalStateKey)\n\n return\n }\n\n frigadeGlobalState[globalStateKey].refreshStateFromAPI = async (\n overrideFlowStateRaw?: FlowStates\n ) => {\n if (this.config.__readOnly) {\n return\n }\n\n const flowStateRaw: FlowStates = overrideFlowStateRaw\n ? overrideFlowStateRaw\n : await this.fetch('/v1/public/flowStates', {\n method: 'POST',\n body: JSON.stringify({\n userId: this.getGlobalState().config.userId,\n groupId: this.getGlobalState().config.groupId,\n context: getContext(this.getGlobalState()),\n } as FlowStateDTO),\n })\n\n const collectionsData: CollectionsList = new Map()\n\n flowStateRaw.collections?.computedOrder?.forEach(\n ({ allowedComponents, collectionId, collectionType, flowId, visible }) => {\n const currentCollection: Collection = collectionsData.get(collectionId) ?? {\n allowedComponents,\n collectionType,\n flows: [],\n }\n\n currentCollection.flows.push({\n flowId,\n visible,\n })\n\n collectionsData.set(collectionId, currentCollection)\n }\n )\n\n if (collectionsData.size > 0) {\n frigadeGlobalState[globalStateKey].collections.ingestCollectionsData(collectionsData)\n if (\n frigadeGlobalState[globalStateKey].collections.collectionsHaveChanged() &&\n // Necessary check to prevent race condition between flow state and collection state\n !overrideFlowStateRaw\n ) {\n this.triggerAllLegacyEventHandlers()\n this.triggerAllEventHandlers()\n }\n }\n\n if (flowStateRaw && flowStateRaw.eligibleFlows) {\n flowStateRaw.eligibleFlows.forEach((statefulFlow) => {\n frigadeGlobalState[globalStateKey].flowStates[statefulFlow.flowSlug] = statefulFlow\n if (!this.flows.find((flow) => flow.id == statefulFlow.flowSlug)) {\n this.flows.push(\n new Flow({\n config: this.config,\n id: statefulFlow.flowSlug,\n })\n )\n } else {\n this.flows.forEach((flow) => {\n if (flow.id == statefulFlow.flowSlug) {\n flow.resyncState(statefulFlow)\n }\n })\n }\n })\n this.hasFailed = false\n } else {\n this.hasFailed = true\n }\n }\n }\n\n await frigadeGlobalState[globalStateKey].refreshStateFromAPI(undefined)\n }\n\n /**\n * @ignore\n */\n private mockFlowStates(globalStateKey: string) {\n Object.keys(this.config.__flowStateOverrides).forEach((flowId) => {\n frigadeGlobalState[globalStateKey].flowStates[flowId] =\n this.config.__flowStateOverrides[flowId]\n\n if (!this.flows.find((flow) => flow.id == flowId)) {\n this.flows.push(\n new Flow({\n config: this.config,\n id: flowId,\n })\n )\n } else {\n this.flows.forEach((flow) => {\n if (flow.id == flowId) {\n flow.resyncState(this.config.__flowStateOverrides[flowId])\n }\n })\n }\n })\n }\n\n /**\n * @ignore\n */\n private async updateConfig(config: FrigadeConfig) {\n this.config = {\n ...this.config,\n ...config,\n }\n if (frigadeGlobalState[getGlobalStateKey(this.config)]) {\n this.getGlobalState().config = this.config\n }\n }\n\n /**\n * @ignore\n */\n private async triggerDeprecatedEventHandlers(\n newState: StatefulFlow,\n previousState?: StatefulFlow\n ) {\n if (newState) {\n this.flows.forEach((flow) => {\n if (flow.id == previousState.flowSlug) {\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(newState)\n handler(flow, lastFlow)\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n })\n }\n })\n }\n }\n\n /**\n * @ignore\n */\n private triggerEventHandlers(newState: StatefulFlow, previousState?: StatefulFlow) {\n if (newState) {\n for (const flow of this.flows) {\n if (flow.id == newState.flowSlug) {\n const lastFlow = this.getGlobalState().previousFlows.get(flow.id)\n flow.resyncState(newState)\n for (const [event, handlers] of this.eventHandlers.entries()) {\n switch (event) {\n case 'flow.complete':\n if (newState.$state.completed && previousState?.$state.completed === false) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n case 'flow.restart':\n if (!newState.$state.started && previousState?.$state.started === true) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n case 'flow.skip':\n if (newState.$state.skipped && previousState?.$state.skipped === false) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n case 'flow.start':\n if (newState.$state.started && previousState?.$state.started === false) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n case 'step.complete':\n for (const step of newState.data.steps ?? []) {\n if (\n step.$state.completed &&\n !previousState?.data.steps.find(\n (previousStepState) =>\n previousStepState.id === step.id && previousStepState.$state.completed\n )\n ) {\n handlers.forEach((handler) =>\n handler(event, flow, lastFlow, flow.steps.get(step.id))\n )\n }\n }\n break\n case 'step.reset':\n for (const step of newState.data.steps ?? []) {\n const previousStep = previousState?.data.steps.find(\n (previousStepState) => previousStepState.id === step.id\n )\n if (\n step.$state.started == false &&\n !step.$state.lastActionAt &&\n previousStep?.$state.started &&\n previousStep?.$state.lastActionAt\n ) {\n handlers.forEach((handler) =>\n handler(event, flow, lastFlow, flow.steps.get(step.id))\n )\n }\n }\n break\n case 'step.skip':\n for (const step of newState.data.steps ?? []) {\n if (\n step.$state.skipped &&\n !previousState?.data.steps.find(\n (previousStepState) =>\n previousStepState.id === step.id && previousStepState.$state.skipped\n )\n ) {\n handlers.forEach((handler) =>\n handler(event, flow, lastFlow, flow.steps.get(step.id))\n )\n }\n }\n break\n case 'step.start':\n for (const step of newState.data.steps ?? []) {\n if (\n step.$state.started &&\n previousState?.data.steps.find(\n (previousStepState) =>\n previousStepState.id === step.id &&\n previousStepState.$state.started === false\n )\n ) {\n handlers.forEach((handler) =>\n handler(event, flow, lastFlow, flow.steps.get(step.id))\n )\n }\n }\n break\n case 'flow.any':\n if (JSON.stringify(newState) !== JSON.stringify(previousState ?? {})) {\n handlers.forEach((handler) => handler(event, flow, lastFlow))\n }\n break\n }\n }\n this.getGlobalState().previousFlows.set(flow.id, cloneFlow(flow))\n }\n }\n }\n }\n\n /**\n * @ignore\n */\n async batchRegister(flowIds: CollectionsRegistryBatch) {\n const flowIdsWithWrappedCallbacks = flowIds.map(async ([flowId, callback]) => {\n const currentFlow = await this.getFlow(flowId)\n const wrappedCallback = (visible: boolean) => {\n const prevFlow = this.getGlobalState().previousFlows.get(flowId)\n\n if (prevFlow?.isVisible !== visible) {\n // TODO: Store these in a hash so we can grab this flow's handler and call it\n this.getGlobalState().onFlowStateChangeHandlers.forEach((handler) => {\n handler(currentFlow, prevFlow)\n this.getGlobalState().previousFlows.set(flowId, cloneFlow(currentFlow))\n })\n }\n\n callback?.(visible)\n }\n\n return [flowId, wrappedCallback] as CollectionsRegistryBatch[number]\n })\n\n Promise.all(flowIdsWithWrappedCallbacks).then((results) => {\n this.getGlobalState().collections.batchRegister(results)\n })\n }\n}\n"],"mappings":"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","names":["TriggerType","FlowStatus","FlowType","uuidv4","frigadeGlobalState","getGlobalStateKey","internalConfig","Fetchable","config","generateGuestId","filteredConfig","_","v","__spreadValues","path","options","__async","getEmptyResponse","gracefulFetch","getHeaders","globalStateKey","getGlobalStateKey","frigadeGlobalState","Flow","Fetchable","config","id","visible","overrideStatefulFlow","_a","_b","_c","_d","_e","_f","statefulFlow","clone","step","index","stepObj","existingStep","key","__spreadProps","__spreadValues","newSteps","properties","__async","thisStep","copy","STARTED_STEP","internalComplete","eventType","optimistic","nextStep","isLastStep","isLastIncompleteStep","nextStepIndex","COMPLETED_STEP","SKIPPED_STEP","COMPLETED_FLOW","NOT_STARTED_STEP","handler","wrapperHandler","flow","previousStep","h","STARTED_FLOW","SKIPPED_FLOW","NOT_STARTED_FLOW","currentStep","steps","previousFlow","variables","resyncState","replaceVariables","str","matches","match","variable","applyVariablesToStep","item","e","action","data","stepId","date","flowStatesRaw","getContext","callback","prevFlow","cloneFlow","SDK_VERSION","NOT_STARTED_STEP","COMPLETED_FLOW","SKIPPED_FLOW","STARTED_FLOW","NOT_STARTED_FLOW","COMPLETED_STEP","SKIPPED_STEP","STARTED_STEP","GUEST_KEY","GUEST_PREFIX","GET_CACHE_PREFIX","LOCAL_STORAGE_PREFIX","REDUNDANT_CALL_MESSAGE","cloneFlow","flow","Flow","clone","obj","getHeaders","config","_a","_b","SDK_VERSION","getLocalStorage","key","isWeb","e","setLocalStorage","value","clearCache","frigadeGlobalState","resetAllLocalStorage","CallQueue","call","response","now","callKey","item","gracefulFetch","url","options","__async","getEmptyResponse","lastCallDataKey","isWebPostRequest","cachedCall","pendingResponse","res","error","body","generateGuestId","guestId","uuidv4","getContext","state","context","__spreadValues","Collections","collectionsData","collectionId","collection","flowId","newCollectionsData","previousCollections","newCollections","newCollection","i","callback","registeredFlow","flowInCollections","item","visibleAPIOverride","flowIdsInThisCollection","otherFlowId","flowIds","visible","_a","Frigade","Fetchable","apiKey","config","__spreadValues","isWeb","event","__async","e","_a","globalStateKey","getGlobalStateKey","frigadeGlobalState","GUEST_PREFIX","userId","properties","__spreadProps","groupId","sessionDTO","lastSessionDTO","flowId","flow","collectionId","collection","enrichedFlows","item","collections","resetAllLocalStorage","clearCache","handler","lastFlow","cloneFlow","h","that","validator","target","key","value","previousState","newState","Collections","overrideFlowStateRaw","_b","flowStateRaw","getContext","collectionsData","allowedComponents","collectionType","visible","currentCollection","statefulFlow","Flow","_c","_d","handlers","step","previousStepState","previousStep","flowIds","flowIdsWithWrappedCallbacks","_0","callback","currentFlow","prevFlow","results"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frigade/js",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "The official Javascript SDK for Frigade.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",