@frigade/js 0.2.39 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,18 +1,197 @@
1
- interface FlowDataRaw {
2
- id: number;
3
- name: string;
4
- description: string;
5
- data: string;
6
- createdAt: string;
7
- modifiedAt: string;
8
- slug: string;
9
- targetingLogic: string;
10
- type: FlowType;
11
- triggerType: TriggerType;
12
- status: FlowStatus;
13
- version: number;
14
- active: boolean;
1
+ interface RulesGraphNode {
2
+ visible: boolean;
3
+ edges: RulesGraphEdge[];
15
4
  }
5
+ interface RulesGraphEdge {
6
+ head: string;
7
+ ruleId: string;
8
+ }
9
+ type RulesGraphRegistryCallback = (visible: boolean) => void;
10
+ declare class RulesGraph {
11
+ private graph;
12
+ private readonly registry;
13
+ private readonly _rawGraphData;
14
+ get rawGraphData(): Record<string, RulesGraphNode>;
15
+ constructor(graphData: Record<string, RulesGraphNode>, registry?: Map<string, RulesGraphRegistryCallback>);
16
+ ingestGraphData(graphData: Record<string, RulesGraphNode>): void;
17
+ fireCallbacks(): void;
18
+ isFlowVisible(flowId: string): boolean;
19
+ register(flowId: string, callback?: RulesGraphRegistryCallback): void;
20
+ unregister(flowId: string): void;
21
+ getRegistry(): Map<string, RulesGraphRegistryCallback>;
22
+ private findRegisteredDescendant;
23
+ }
24
+
25
+ interface FrigadeGlobalState {
26
+ refreshStateFromAPI: () => Promise<void>;
27
+ flowStates: Record<string, StatefulFlow>;
28
+ rulesGraph: RulesGraph;
29
+ onFlowStateChangeHandlerWrappers: Map<(flow: Flow, previousFlow: Flow) => void, (flow: Flow, previousFlow: Flow) => void>;
30
+ onStepStateChangeHandlerWrappers: Map<(step: FlowStep, previousStep: FlowStep) => void, (flow: Flow, previousFlow: Flow) => void>;
31
+ onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[];
32
+ previousFlows: Map<string, Flow>;
33
+ variables: Record<string, Record<string, any>>;
34
+ }
35
+
36
+ declare class Fetchable {
37
+ config: FrigadeConfig;
38
+ constructor(config: FrigadeConfig);
39
+ /**
40
+ * @ignore
41
+ */
42
+ fetch(path: string, options?: Record<any, any>): Promise<any>;
43
+ private getAPIUrl;
44
+ /**
45
+ * @ignore
46
+ */
47
+ protected getGlobalState(): FrigadeGlobalState;
48
+ }
49
+
50
+ declare class Flow extends Fetchable {
51
+ /**
52
+ * The Flow's ID.
53
+ */
54
+ id: string;
55
+ /**
56
+ * Ordered map of the Steps in the Flow.
57
+ * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.
58
+ */
59
+ steps: Map<string, FlowStep>;
60
+ /**
61
+ * The user-facing title of the Flow, if defined at the top level of the YAML config.
62
+ */
63
+ title?: string;
64
+ /**
65
+ * The user-facing description of the Flow, if defined at the top level of the YAML config.
66
+ */
67
+ subtitle?: string;
68
+ /**
69
+ * The metadata of the Flow.
70
+ * @ignore
71
+ */
72
+ rawData: StatefulFlow;
73
+ /**
74
+ * Whether the Flow is completed or not.
75
+ */
76
+ isCompleted: boolean;
77
+ /**
78
+ * Whether the Flow is started or not.
79
+ */
80
+ isStarted: boolean;
81
+ /**
82
+ * Whether the Flow has been skipped or not.
83
+ */
84
+ isSkipped: boolean;
85
+ /**
86
+ * @ignore
87
+ */
88
+ private _isVisible;
89
+ /**
90
+ * Whether the Flow is visible to the user based on the current user/group's state.
91
+ */
92
+ get isVisible(): boolean;
93
+ set isVisible(visible: boolean);
94
+ /**
95
+ * @ignore
96
+ */
97
+ private lastStepUpdate;
98
+ constructor({ config, id }: {
99
+ config: FrigadeConfig;
100
+ id: string;
101
+ });
102
+ /**
103
+ * Reload the Flow data from the server
104
+ */
105
+ reload(): void;
106
+ /**
107
+ * @ignore
108
+ */
109
+ resyncState(overrideStatefulFlow?: StatefulFlow): void;
110
+ /**
111
+ * @ignore
112
+ */
113
+ private initStepFromStatefulStep;
114
+ /**
115
+ * @ignore
116
+ */
117
+ private init;
118
+ /**
119
+ * Marks the flow started
120
+ */
121
+ start(properties?: Record<string | number, any>): Promise<void>;
122
+ /**
123
+ * Marks the flow completed
124
+ */
125
+ complete(properties?: Record<string | number, any>): Promise<void>;
126
+ /**
127
+ * Marks the flow skipped
128
+ */
129
+ skip(properties?: Record<string | number, any>): Promise<void>;
130
+ /**
131
+ * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.
132
+ */
133
+ forward(properties?: Record<string | number, any>): Promise<void>;
134
+ /**
135
+ * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.
136
+ */
137
+ back(properties?: Record<string | number, any>): Promise<void>;
138
+ /**
139
+ * Restarts the flow/marks it not started
140
+ */
141
+ restart(): Promise<void>;
142
+ /**
143
+ * Get a step by index
144
+ * @param index
145
+ */
146
+ getStepByIndex(index: number): FlowStep | undefined;
147
+ /**
148
+ * Gets current step
149
+ */
150
+ getCurrentStep(): FlowStep;
151
+ /**
152
+ * Get the index of the current step. Starts at 0
153
+ */
154
+ getCurrentStepIndex(): number;
155
+ /**
156
+ * Get the number of completed steps for the current user in the current flow
157
+ */
158
+ getNumberOfCompletedSteps(): number;
159
+ /**
160
+ * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.
161
+ */
162
+ getNumberOfAvailableSteps(): number;
163
+ /**
164
+ * @ignore
165
+ */
166
+ onStateChange(handler: (flow: Flow, previousFlow: Flow) => void): void;
167
+ /**
168
+ * @ignore
169
+ */
170
+ removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void): void;
171
+ /**
172
+ * @ignore
173
+ */
174
+ applyVariables(variables: Record<string, any>): void;
175
+ /**
176
+ * @ignore
177
+ */
178
+ private getStatefulFlow;
179
+ /**
180
+ * @ignore
181
+ */
182
+ private refreshStateFromAPI;
183
+ /**
184
+ * @ignore
185
+ */
186
+ private optimisticallyMarkFlowCompleted;
187
+ /**
188
+ * @ignore
189
+ */
190
+ private optimisticallyMarkFlowSkipped;
191
+ register(callback?: RulesGraphRegistryCallback): void;
192
+ unregister(): void;
193
+ }
194
+
16
195
  declare enum TriggerType {
17
196
  MANUAL = "MANUAL",
18
197
  AUTOMATIC = "AUTOMATIC"
@@ -22,11 +201,8 @@ declare enum FlowStatus {
22
201
  ACTIVE = "ACTIVE",
23
202
  ARCHIVED = "ARCHIVED"
24
203
  }
25
- interface FlowStep {
26
- /**
27
- * Unique identifier for the step.
28
- */
29
- id: string;
204
+ type StepAction = 'flow.back' | 'flow.complete' | 'flow.forward' | 'flow.restart' | 'flow.skip' | 'flow.start' | 'step.complete' | 'step.reset' | 'step.start' | false;
205
+ interface FlowStep extends StatefulStep {
30
206
  /**
31
207
  * Order of the step in the Flow.
32
208
  */
@@ -44,27 +220,75 @@ interface FlowStep {
44
220
  */
45
221
  subtitle?: string;
46
222
  /**
223
+ * Config for the primary button in this step
224
+ */
225
+ primaryButton?: {
226
+ /**
227
+ * Primary button action. (defaults to step.complete)
228
+ */
229
+ action?: StepAction;
230
+ /**
231
+ * Primary button URI target (defaults to _self).
232
+ */
233
+ target?: string;
234
+ /**
235
+ * Primary button title. If omitted, the primary button will not be shown.
236
+ */
237
+ title?: string;
238
+ /**
239
+ * Primary button URI.
240
+ */
241
+ uri?: string;
242
+ };
243
+ /**
244
+ * @deprecated use primaryButton.title instead
47
245
  * Primary button title. If omitted, the primary button will not be shown.
48
246
  */
49
247
  primaryButtonTitle?: string;
50
248
  /**
249
+ * @deprecated use primaryButton.uri instead
51
250
  * Primary button URI.
52
251
  */
53
252
  primaryButtonUri?: string;
54
253
  /**
55
- * Primary button URI target (either _blank or _self).
254
+ * @deprecated use primaryButton.target instead
255
+ * Primary button URI target (defaults to _self).
56
256
  */
57
257
  primaryButtonUriTarget?: string;
58
258
  /**
259
+ * Config for the secondary button in this step
260
+ */
261
+ secondaryButton?: {
262
+ /**
263
+ * Secondary button action. (defaults to step.complete)
264
+ */
265
+ action?: StepAction;
266
+ /**
267
+ * Secondary button URI target (defaults to _self).
268
+ */
269
+ target?: string;
270
+ /**
271
+ * Secondary button title. If omitted, the secondary button will not be shown.
272
+ */
273
+ title?: string;
274
+ /**
275
+ * Secondary button URI.
276
+ */
277
+ uri?: string;
278
+ };
279
+ /**
280
+ * @deprecated use secondaryButton.title instead
59
281
  * Secondary button title. If omitted, the secondary button will not be shown.
60
282
  */
61
283
  secondaryButtonTitle?: string;
62
284
  /**
285
+ * @deprecated use secondaryButton.uri instead
63
286
  * Secondary button URI.
64
287
  */
65
288
  secondaryButtonUri?: string;
66
289
  /**
67
- * Secondary button URI target (either _blank or _self)
290
+ * @deprecated use secondaryButton.target instead
291
+ * Secondary button URI target (defaults to _self)
68
292
  */
69
293
  secondaryButtonUriTarget?: string;
70
294
  /**
@@ -87,26 +311,6 @@ interface FlowStep {
87
311
  * Automatically mark the step as completed when the primary button is clicked. Default is false.
88
312
  */
89
313
  autoMarkCompleted?: boolean;
90
- /**
91
- * Whether the step has been completed (equivalent to step status === COMPLETED_STEP).
92
- */
93
- isCompleted: boolean;
94
- /**
95
- * Whether the step has been completed (equivalent to step status === COMPLETED_STEP).
96
- */
97
- isStarted: boolean;
98
- /**
99
- * Whether the step is blocked (can't be accessed yet) based on `startCriteria`.
100
- */
101
- isBlocked: boolean;
102
- /**
103
- * Whether the step is hidden (not shown in the list view) based on `visibilityCriteria`.
104
- */
105
- isHidden: boolean;
106
- /**
107
- * Last state update.
108
- */
109
- lastActionAt?: Date;
110
314
  /**
111
315
  * @ignore
112
316
  */
@@ -151,13 +355,17 @@ interface FlowStep {
151
355
  */
152
356
  reset: () => Promise<void>;
153
357
  /**
154
- * Event handler for this given step's state changes.
358
+ * Event handler called when this step's state changes.
155
359
  */
156
360
  onStateChange: (callback: (step: FlowStep, previousStep?: FlowStep) => void) => void;
157
361
  /**
158
362
  * Removes the given callback from the list of event handlers.
159
363
  */
160
364
  removeStateChangeHandler: (callback: (step: FlowStep, previousStep?: FlowStep) => void) => void;
365
+ /**
366
+ * Reference to this step's parent Flow
367
+ */
368
+ flow: Flow;
161
369
  }
162
370
  interface FrigadeConfig {
163
371
  /**
@@ -192,23 +400,34 @@ interface FrigadeConfig {
192
400
  */
193
401
  __instanceId?: string;
194
402
  }
195
- interface UserFlowState {
196
- flowId: string;
197
- flowState: 'COMPLETED_FLOW' | 'STARTED_FLOW' | 'SKIPPED_FLOW' | 'NOT_STARTED_FLOW';
198
- lastStepId: string;
199
- userId: string;
200
- foreignUserId: string;
201
- stepStates: Record<string, UserFlowStepState>;
202
- shouldTrigger: boolean;
403
+ interface StatefulStep {
404
+ id: string;
405
+ $state: {
406
+ completed: boolean;
407
+ started: boolean;
408
+ visible: boolean;
409
+ blocked: boolean;
410
+ lastActionAt?: Date;
411
+ };
412
+ [key: string]: any;
203
413
  }
204
- interface UserFlowStepState {
205
- stepId: string;
414
+ interface StatefulFlow {
206
415
  flowSlug: string;
207
- actionType: 'NOT_STARTED_STEP' | 'STARTED_STEP' | 'COMPLETED_STEP';
208
- createdAt: string;
209
- blocked: boolean;
210
- hidden: boolean;
211
- lastActionAt?: string;
416
+ flowName: string;
417
+ flowType: FlowType;
418
+ data: {
419
+ steps: StatefulStep[];
420
+ [key: string]: any;
421
+ };
422
+ $state: {
423
+ currentStepId: string;
424
+ currentStepIndex: number;
425
+ completed: boolean;
426
+ started: boolean;
427
+ skipped: boolean;
428
+ visible: boolean;
429
+ lastActionAt?: Date;
430
+ };
212
431
  }
213
432
  declare enum FlowType {
214
433
  ANNOUNCEMENT = "ANNOUNCEMENT",
@@ -224,174 +443,6 @@ declare enum FlowType {
224
443
  CARD = "CARD"
225
444
  }
226
445
 
227
- interface FrigadeGlobalState {
228
- refreshUserFlowStates: () => Promise<void>;
229
- userFlowStates: Record<string, UserFlowState>;
230
- onFlowStateChangeHandlerWrappers: Map<(flow: Flow, previousFlow: Flow) => void, (flow: Flow, previousFlow: Flow) => void>;
231
- onStepStateChangeHandlerWrappers: Map<(step: FlowStep, previousStep: FlowStep) => void, (flow: Flow, previousFlow: Flow) => void>;
232
- onFlowStateChangeHandlers: ((flow: Flow, previousFlow: Flow) => void)[];
233
- previousFlows: Map<string, Flow>;
234
- variables: Record<string, Record<string, any>>;
235
- }
236
-
237
- declare class Fetchable {
238
- config: FrigadeConfig;
239
- constructor(config: FrigadeConfig);
240
- /**
241
- * @ignore
242
- */
243
- fetch(path: string, options?: Record<any, any>): Promise<any>;
244
- private getAPIUrl;
245
- /**
246
- * @ignore
247
- */
248
- protected getGlobalState(): FrigadeGlobalState;
249
- }
250
-
251
- declare class Flow extends Fetchable {
252
- /**
253
- * The Flow's ID.
254
- */
255
- id: string;
256
- /**
257
- * The raw data defined in `config.yml` as a JSON decoded object.
258
- * @ignore
259
- */
260
- configYmlAsJson: any;
261
- /**
262
- * Ordered map of the Steps in the Flow.
263
- * See [Flow Step Definition](https://docs.frigade.com/v2/sdk/js/step) for more information.
264
- */
265
- steps: Map<string, FlowStep>;
266
- /**
267
- * The user-facing title of the Flow, if defined at the top level of the YAML config.
268
- */
269
- title?: string;
270
- /**
271
- * The user-facing description of the Flow, if defined at the top level of the YAML config.
272
- */
273
- subtitle?: string;
274
- /**
275
- * The metadata of the Flow.
276
- * @ignore
277
- */
278
- rawData: FlowDataRaw;
279
- /**
280
- * Whether the Flow is completed or not.
281
- */
282
- isCompleted: boolean;
283
- /**
284
- * Whether the Flow is started or not.
285
- */
286
- isStarted: boolean;
287
- /**
288
- * Whether the Flow has been skipped or not.
289
- */
290
- isSkipped: boolean;
291
- /**
292
- * Whether the Flow is visible to the user based on the current user/group's state.
293
- */
294
- isVisible: boolean;
295
- /**
296
- * Whether the Flow targeting logic/audience matches the current user/group.
297
- */
298
- isTargeted: boolean;
299
- /**
300
- * @ignore
301
- */
302
- private readonly flowDataRaw;
303
- /**
304
- * @ignore
305
- */
306
- private userFlowStateRaw?;
307
- /**
308
- * @ignore
309
- */
310
- private lastStepUpdate;
311
- constructor(config: FrigadeConfig, flowDataRaw: FlowDataRaw);
312
- /**
313
- * Reload the Flow data from the server
314
- */
315
- reload(): void;
316
- /**
317
- * @ignore
318
- */
319
- private initFromRawData;
320
- /**
321
- * Marks the flow started
322
- */
323
- start(properties?: Record<string | number, any>): Promise<void>;
324
- /**
325
- * Marks the flow completed
326
- */
327
- complete(properties?: Record<string | number, any>): Promise<void>;
328
- /**
329
- * @ignore
330
- */
331
- private optimisticallyMarkFlowCompleted;
332
- /**
333
- * @ignore
334
- */
335
- private optimisticallyMarkFlowSkipped;
336
- /**
337
- * Marks the flow skipped
338
- */
339
- skip(properties?: Record<string | number, any>): Promise<void>;
340
- /**
341
- * Navigates the flow to the next step if one exists. This will mark that step started, but will not complete the previous step.
342
- */
343
- forward(properties?: Record<string | number, any>): Promise<void>;
344
- /**
345
- * Navigates the flow to the previous step if one exists. This will mark that step started, but will not complete the previous step.
346
- */
347
- back(properties?: Record<string | number, any>): Promise<void>;
348
- /**
349
- * Restarts the flow/marks it not started
350
- */
351
- restart(): Promise<void>;
352
- /**
353
- * Get a step by index
354
- * @param index
355
- */
356
- getStepByIndex(index: number): FlowStep | undefined;
357
- /**
358
- * Gets current step
359
- */
360
- getCurrentStep(): FlowStep;
361
- /**
362
- * Get the index of the current step. Starts at 0
363
- */
364
- getCurrentStepIndex(): number;
365
- /**
366
- * Get the number of completed steps for the current user in the current flow
367
- */
368
- getNumberOfCompletedSteps(): number;
369
- /**
370
- * Get the number of available steps for the current user in the current flow. This is the number of steps that are not hidden.
371
- */
372
- getNumberOfAvailableSteps(): number;
373
- /**
374
- * @ignore
375
- */
376
- onStateChange(handler: (flow: Flow, previousFlow: Flow) => void): void;
377
- /**
378
- * @ignore
379
- */
380
- removeStateChangeHandler(handler: (flow: Flow, previousFlow: Flow) => void): void;
381
- /**
382
- * @ignore
383
- */
384
- applyVariables(variables: Record<string, any>): void;
385
- /**
386
- * @ignore
387
- */
388
- private getUserFlowState;
389
- /**
390
- * @ignore
391
- */
392
- private refreshUserFlowState;
393
- }
394
-
395
446
  declare class Frigade extends Fetchable {
396
447
  /**
397
448
  * @ignore
@@ -473,11 +524,7 @@ declare class Frigade extends Fetchable {
473
524
  /**
474
525
  * @ignore
475
526
  */
476
- private refreshUserFlowStates;
477
- /**
478
- * @ignore
479
- */
480
- private refreshFlows;
527
+ private refreshStateFromAPI;
481
528
  /**
482
529
  * @ignore
483
530
  */
@@ -485,7 +532,7 @@ declare class Frigade extends Fetchable {
485
532
  /**
486
533
  * @ignore
487
534
  */
488
- private mockUserFlowStates;
535
+ private mockFlowStates;
489
536
  /**
490
537
  * @ignore
491
538
  */
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- var at=Object.defineProperty,ot=Object.defineProperties;var rt=Object.getOwnPropertyDescriptors;var X=Object.getOwnPropertySymbols;var nt=Object.prototype.hasOwnProperty,lt=Object.prototype.propertyIsEnumerable;var z=(s,o,t)=>o in s?at(s,o,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[o]=t,F=(s,o)=>{for(var t in o||(o={}))nt.call(o,t)&&z(s,t,o[t]);if(X)for(var t of X(o))lt.call(o,t)&&z(s,t,o[t]);return s},G=(s,o)=>ot(s,rt(o));var d=(s,o,t)=>new Promise((e,i)=>{var a=h=>{try{r(t.next(h))}catch(p){i(p)}},g=h=>{try{r(t.throw(h))}catch(p){i(p)}},r=h=>h.done?e(h.value):Promise.resolve(h.value).then(a,g);r((t=t.apply(s,o)).next())});var L=(t=>(t.MANUAL="MANUAL",t.AUTOMATIC="AUTOMATIC",t))(L||{}),H=(e=>(e.DRAFT="DRAFT",e.ACTIVE="ACTIVE",e.ARCHIVED="ARCHIVED",e))(H||{}),x=(S=>(S.ANNOUNCEMENT="ANNOUNCEMENT",S.CHECKLIST="CHECKLIST",S.FORM="FORM",S.TOUR="TOUR",S.SUPPORT="SUPPORT",S.CUSTOM="CUSTOM",S.BANNER="BANNER",S.EMBEDDED_TIP="EMBEDDED_TIP",S.NPS_SURVEY="NPS_SURVEY",S.SURVEY="SURVEY",S.CARD="CARD",S))(x||{});var q="0.2.20";import dt from"cross-fetch";import{v4 as gt}from"uuid";var f={};function v(s){var o,t;return`${s.__instanceId}-${s.apiKey}:${(o=s.userId)!=null?o:""}:${(t=s.groupId)!=null?t:""}`}var R=class{constructor(o){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:tt(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(o).filter(([e,i])=>i!=null));this.config=F(F({},this.config),t)}fetch(o,t){return d(this,null,function*(){return this.config.__readOnly?b():Z(this.getAPIUrl(o),F(F({keepalive:!0},t!=null?t:{}),Q(this.config.apiKey)))})}getAPIUrl(o){let t="/v1/public";return new URL(`${t}${o}`,this.config.apiUrl.replace(t,"")).toString()}getGlobalState(){let o=v(this.config);if(!f[o])throw new Error("Frigade not initialized");return f[o]}};var T=class extends R{constructor(t,e){super(t);this.isVisible=!1;this.isTargeted=!1;this.lastStepUpdate=new Map;this.flowDataRaw=e,this.initFromRawData(e)}reload(){this.initFromRawData(this.flowDataRaw)}initFromRawData(t){var p,O;let e=JSON.parse(t.data),i=(O=(p=e.steps)!=null?p:e.data)!=null?O:[];this.id=t.slug,this.rawData=t,this.configYmlAsJson=e,this.title=this.configYmlAsJson.title,this.subtitle=this.configYmlAsJson.subtitle;let a=this.getUserFlowState();if(!a)return;this.userFlowStateRaw=a,this.isCompleted=a.flowState==P,this.isStarted=a.flowState==D,this.isSkipped=a.flowState==N;let g=this.isCompleted||this.isSkipped,r=t.targetingLogic&&a.shouldTrigger===!1;this.isVisible=!g&&!r,this.flowDataRaw.active===!1&&(this.isVisible=!1),this.isTargeted=t.targetingLogic?r===!1:!0;let h=new Map;i.forEach((S,$)=>{let E=a.stepStates[S.id],A=G(F({},S),{isCompleted:E.actionType==I,isStarted:E.actionType==y,isHidden:E.hidden,isBlocked:E.blocked,lastActionAt:E.lastActionAt?new Date(E.lastActionAt):void 0,order:$});A.start=n=>d(this,null,function*(){let l=this.steps.get(S.id);if(this.getCurrentStep().id===l.id&&l.isStarted)return;l.isStarted=!0;let w=m(this.getGlobalState().userFlowStates[this.id]);w.stepStates[l.id].actionType=y,w.stepStates[l.id].lastActionAt=new Date().toISOString(),w.lastStepId=l.id,this.getGlobalState().userFlowStates[this.id]=w,l.isCompleted||(yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:l.id,data:n!=null?n:{},createdAt:n!=null&&n.createdAt?new Date(n.createdAt):new Date().toISOString(),actionType:y})}),yield this.refreshUserFlowState());let u=this.getUserFlowState();l.isCompleted=u.stepStates[l.id].actionType==I,l.isStarted=u.stepStates[l.id].actionType==y,l.lastActionAt=new Date}),A.complete=n=>d(this,null,function*(){let l=this.steps.get(S.id);if(l.isCompleted)return;let u=this.getNumberOfCompletedSteps()+1==this.steps.size;l.isCompleted=!0,this.isStarted=!0;let c=m(this.getGlobalState().userFlowStates[this.id]);c.stepStates[l.id].actionType=I,c.stepStates[l.id].lastActionAt=new Date().toISOString(),c.flowState=u?P:D;let _=Array.from(this.steps.keys())[$+1];if(_){c.lastStepId=_,c.stepStates[_].actionType=y;let Y=new Date;c.stepStates[_].lastActionAt=Y.toISOString(),this.steps.get(_).isStarted=!0,this.steps.get(_).lastActionAt=Y}u&&this.optimisticallyMarkFlowCompleted(),this.getGlobalState().userFlowStates[this.id]=c,yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:l.id,data:n!=null?n:{},createdAt:n!=null&&n.createdAt?new Date(n.createdAt):new Date().toISOString(),actionType:I})}),yield this.refreshUserFlowState();let j=this.getUserFlowState();l.isCompleted=j.stepStates[l.id].actionType==I,l.isStarted=j.stepStates[l.id].actionType==y,l.lastActionAt=new Date}),A.reset=()=>d(this,null,function*(){let n=this.steps.get(S.id);if(!n.isCompleted)return;n.isCompleted=!1,n.isStarted=!1,n.lastActionAt=void 0;let l=m(this.getGlobalState().userFlowStates[this.id]);l.stepStates[n.id].actionType=M,l.stepStates[n.id].lastActionAt=void 0,l.flowState=D,this.getGlobalState().userFlowStates[this.id]=l,yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:n.id,data:{},createdAt:new Date().toISOString(),actionType:M})}),yield this.refreshUserFlowState();let w=this.getUserFlowState();n.isCompleted=w.stepStates[n.id].actionType==I,n.isStarted=w.stepStates[n.id].actionType==y,n.lastActionAt=void 0}),A.onStateChange=n=>{let l=w=>{if(w.id!==this.id)return;let u=w.steps.get(S.id),c=this.lastStepUpdate.get(n);(u.isCompleted!==(c==null?void 0:c.isCompleted)||u.isStarted!==(c==null?void 0:c.isStarted)||u.isHidden!==(c==null?void 0:c.isHidden)||u.isBlocked!==(c==null?void 0:c.isBlocked))&&(n(u,c!=null?c:m(u)),this.lastStepUpdate.set(n,m(u)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(n,l),this.getGlobalState().onFlowStateChangeHandlers.push(l)},A.removeStateChangeHandler=n=>{let l=this.getGlobalState().onStepStateChangeHandlerWrappers.get(n);l&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(w=>w!==l))},h.set(S.id,A)}),this.steps=h,this.getGlobalState().variables&&this.getGlobalState().variables[this.id]&&Object.keys(this.getGlobalState().variables[this.id]).length>0&&this.applyVariables(this.getGlobalState().variables[this.id])}start(t){return d(this,null,function*(){if(this.isStarted||this.isCompleted)return;this.isStarted=!0;let e=m(this.getGlobalState().userFlowStates[this.id]);e.flowState=D,this.getGlobalState().userFlowStates[this.id]=e,yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t!=null?t:{},createdAt:new Date().toISOString(),actionType:D})}),yield this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)})}complete(t){return d(this,null,function*(){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t!=null?t:{},createdAt:t!=null&&t.createdAt?new Date(t.createdAt):new Date().toISOString(),actionType:P})}),yield this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))})}optimisticallyMarkFlowCompleted(){this.isStarted=!0,this.isCompleted=!0;let t=m(this.getGlobalState().userFlowStates[this.id]);t.flowState=P,this.getGlobalState().userFlowStates[this.id]=t,this.isVisible=!1}optimisticallyMarkFlowSkipped(){this.isSkipped=!0;let t=m(this.getGlobalState().userFlowStates[this.id]);t.flowState=N,this.getGlobalState().userFlowStates[this.id]=t,this.isVisible=!1}skip(t){return d(this,null,function*(){this.isSkipped||(this.optimisticallyMarkFlowSkipped(),yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t!=null?t:{},createdAt:t!=null&&t.createdAt?new Date(t.createdAt):new Date().toISOString(),actionType:N})}),yield this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw))})}forward(t){return d(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e&&(yield e.start(t))})}back(t){return d(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&(yield e.start(t))})}restart(){return d(this,null,function*(){yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:et})}),yield this.refreshUserFlowState(),this.initFromRawData(this.flowDataRaw)})}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let t=Array.from(this.steps.keys()).find(i=>this.steps.get(i).isCompleted===!1&&this.steps.get(i).isHidden===!1);Array.from(this.steps.keys()).forEach(i=>{var a,g;this.steps.get(i).isStarted&&this.steps.get(i).lastActionAt&&this.steps.get(i).lastActionAt>((g=(a=this.steps.get(t))==null?void 0:a.lastActionAt)!=null?g:new Date(0))&&(t=i)});let e=t!=null?t:Array.from(this.steps.keys())[0];return this.steps.get(e)}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.isCompleted).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>!t.isHidden).length}onStateChange(t){let e=(i,a)=>{(i.id===this.id&&(i.isCompleted!==a.isCompleted||i.isStarted!==a.isStarted||i.isSkipped!==a.isSkipped||i.isVisible!==a.isVisible)||JSON.stringify(i.steps)!==JSON.stringify(a.steps))&&t(i,a)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,e),this.getGlobalState().onFlowStateChangeHandlers.push(e)}removeStateChangeHandler(t){let e=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);e&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(i=>i!==e))}applyVariables(t){var i,a;let e=g=>{let r=g.match(/\${(.*?)}/g);return r&&r.forEach(h=>{let p=h.replace("${","").replace("}","");t[p]&&(g=g.replace(h,t[p]))}),g};this.title=e((i=this.title)!=null?i:""),this.subtitle=e((a=this.subtitle)!=null?a:""),this.steps.forEach(g=>{Object.keys(g).forEach(r=>{typeof g[r]=="string"&&(g[r]=e(g[r]))})}),this.getGlobalState().variables={},this.getGlobalState().variables[this.id]=t}getUserFlowState(){return this.getGlobalState().userFlowStates[this.id]}refreshUserFlowState(){return d(this,null,function*(){yield this.getGlobalState().refreshUserFlowStates()})}};var M="NOT_STARTED_STEP",P="COMPLETED_FLOW",N="SKIPPED_FLOW",D="STARTED_FLOW",et="NOT_STARTED_FLOW",I="COMPLETED_STEP",y="STARTED_STEP",ct="frigade-last-call-at-",ht="frigade-last-call-data-",it="frigade-guest-key",J="guest_",St="get-cache-";var ft=1e3,K="fr-js-";function U(s){let o=new T(s.config,s.rawData);return o.isCompleted=s.isCompleted,o.isStarted=s.isStarted,o.isSkipped=s.isSkipped,o.isVisible=s.isVisible,o.steps=s.steps,o}function m(s){return JSON.parse(JSON.stringify(s))}function Q(s){return{headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json","X-Frigade-SDK-Version":q,"X-Frigade-SDK-Platform":"Javascript"}}}function k(s){return C()?window.localStorage.getItem(`${K}${s}`):null}function W(s,o){C()&&window.localStorage.setItem(`${K}${s}`,o)}function V(){Object.keys(f).forEach(s=>{s.startsWith(St)&&delete f[s]})}function st(){C()&&Object.keys(window.localStorage).forEach(s=>{s.startsWith(K)&&window.localStorage.removeItem(s)})}function Z(s,o){return d(this,null,function*(){let t=ct+s,e=ht+s;if(C()&&o&&o.body&&o.method==="POST"){let a=k(t),g=k(e);if(a&&g&&g==o.body){let r=new Date(a);if(new Date().getTime()-r.getTime()<ft)return b()}W(t,new Date().toISOString()),W(e,o.body),V()}let i;try{i=dt(s,o),i=yield i}catch(a){return b(a)}if(!i)return b("Received an empty response");if(i.status>=400)return b(i.statusText);try{if(i.status===204||i.status===201)return b();let a=yield i.json();return a.error?b(a.error):a}catch(a){return b(a)}})}function b(s){return s&&console.log("Call to Frigade failed",s),{json:()=>({})}}function tt(){if(C()){let s=k(it);return s||(s=`${J}${gt()}`,W(it,s)),s}}function C(){return typeof window!="undefined"&&typeof window.document!="undefined"&&typeof window.localStorage!="undefined"}var B=class extends R{constructor(t,e){super(F({apiKey:t},e));this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=()=>d(this,null,function*(){document.visibilityState==="visible"&&(yield this.refreshFlows(),yield this.refreshUserFlowStates(),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,U(t))})}))});this.init(this.config),C()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(C()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=v(this.config);f[t]&&(f[t].onFlowStateChangeHandlers=[])}}init(t){return d(this,null,function*(){return this.config=F(F({},this.config),t),this.initPromise=(()=>d(this,null,function*(){var e;this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(J))&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})),yield this.refreshUserFlowStates(),yield this.refreshFlows()}))(),this.initPromise})}identify(t,e){return d(this,null,function*(){this.config=G(F({},this.config),{userId:t}),yield this.initIfNeeded(),yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),yield this.resync()})}group(t,e){return d(this,null,function*(){yield this.initIfNeeded(),this.config.groupId=t,yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:e})}),yield this.resync()})}track(t,e){return d(this,null,function*(){if(yield this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})})),yield this.resync()})}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}getFlow(t){return d(this,null,function*(){return yield this.initIfNeeded(),this.flows.find(e=>e.id==t)})}getFlows(){return d(this,null,function*(){return yield this.initIfNeeded(),this.flows})}reload(){return d(this,null,function*(){st(),V(),yield this.refreshUserFlowStates(),yield this.refreshFlows(),this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,U(t))})})})}resync(){return d(this,null,function*(){this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,U(t))})})})}onStateChange(t){return d(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers.push(t)})}hasFailedToLoad(){return this.hasFailed}removeStateChangeHandler(t){return d(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(e=>e!==t)})}initIfNeeded(){return d(this,null,function*(){return this.initPromise!==null?this.initPromise:this.init(this.config)})}refreshUserFlowStates(){return d(this,null,function*(){let t=v(this.config);if(!f[t]){let e=this,i={set:function(a,g,r){return a[g]&&a[g].flowState&&(JSON.stringify(a[g].flowState)!==JSON.stringify(r==null?void 0:r.flowState)||JSON.stringify(a[g].stepStates)!==JSON.stringify(r==null?void 0:r.stepStates)||JSON.stringify(a[g].shouldTrigger)!==JSON.stringify(r==null?void 0:r.shouldTrigger))&&e.triggerEventHandlers(a[g]),a[g]=r,!0}};if(f[t]={refreshUserFlowStates:()=>d(this,null,function*(){}),userFlowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map,variables:{}},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockUserFlowStates(t);return}f[t].refreshUserFlowStates=()=>d(this,null,function*(){if(this.config.__readOnly)return;let a=yield this.fetch(`/userFlowStates?foreignUserId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&foreignUserGroupId=${encodeURIComponent(this.config.groupId)}`:""}`);a&&a.data?(a.data.forEach(r=>{let h=!1,p=f[t].userFlowStates[r.flowId];p&&p.shouldTrigger==!1&&r.shouldTrigger==!0&&(h=!0),f[t].userFlowStates[r.flowId]=r,h&&this.flows.forEach(O=>{O.id==r.flowId&&(O.reload(),this.triggerEventHandlers(f[t].userFlowStates[O.id]))})}),this.hasFailed=!1):this.hasFailed=!0})}yield f[t].refreshUserFlowStates()})}refreshFlows(){return d(this,null,function*(){if(this.flows=[],this.config.__flowConfigOverrides){this.mockFlowConfigs();return}let t=yield this.fetch("/flows");t&&t.data?t.data.forEach(i=>{this.flows.push(new T(this.config,i)),this.getGlobalState().previousFlows.set(i.slug,U(this.flows[this.flows.length-1]))}):this.hasFailed=!0})}mockFlowConfigs(){Object.keys(this.config.__flowConfigOverrides).forEach(t=>{this.flows.push(new T(this.config,{id:-1,name:"",description:"",data:this.config.__flowConfigOverrides[t],createdAt:new Date().toISOString(),modifiedAt:new Date().toISOString(),slug:t,targetingLogic:"",type:"CHECKLIST",triggerType:"MANUAL",status:"ACTIVE",version:1,active:!0}))})}mockUserFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var a,g;let i=JSON.parse(this.config.__flowConfigOverrides[e]);f[t].userFlowStates[e]={flowId:e,flowState:"NOT_STARTED_FLOW",lastStepId:null,userId:this.config.userId,foreignUserId:this.config.userId,stepStates:(g=(a=i==null?void 0:i.steps)==null?void 0:a.reduce((r,h)=>(r[h.id]={stepId:h.id,flowSlug:e,actionType:"NOT_STARTED_STEP",createdAt:new Date().toISOString(),blocked:!1,hidden:!1},r),{}))!=null?g:{},shouldTrigger:!1}})}triggerEventHandlers(t){return d(this,null,function*(){t&&this.flows.forEach(e=>{e.id==t.flowId&&this.getGlobalState().onFlowStateChangeHandlers.forEach(i=>{let a=this.getGlobalState().previousFlows.get(e.id);i(e,a),this.getGlobalState().previousFlows.set(e.id,U(e))})})})}};export{T as Flow,H as FlowStatus,x as FlowType,B as Frigade,L as TriggerType};
2
+ var Z=Object.defineProperty,tt=Object.defineProperties;var et=Object.getOwnPropertyDescriptors;var D=Object.getOwnPropertySymbols;var it=Object.prototype.hasOwnProperty,st=Object.prototype.propertyIsEnumerable;var $=(o,a,t)=>a in o?Z(o,a,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[a]=t,p=(o,a)=>{for(var t in a||(a={}))it.call(a,t)&&$(o,t,a[t]);if(D)for(var t of D(a))st.call(a,t)&&$(o,t,a[t]);return o},y=(o,a)=>tt(o,et(a));var g=(o,a,t)=>new Promise((e,i)=>{var s=n=>{try{r(t.next(n))}catch(c){i(c)}},l=n=>{try{r(t.throw(n))}catch(c){i(c)}},r=n=>n.done?e(n.value):Promise.resolve(n.value).then(s,l);r((t=t.apply(o,a)).next())});var N="0.2.20";import at from"cross-fetch";import{v4 as rt}from"uuid";var h={};function I(o){var a,t;return`${o.__instanceId}-${o.apiKey}:${(a=o.userId)!=null?a:""}:${(t=o.groupId)!=null?t:""}`}var F=class{constructor(a){this.config={apiKey:"",apiUrl:"https://api.frigade.com/v1/public",userId:k(),__instanceId:Math.random().toString(36).substring(7)};let t=Object.fromEntries(Object.entries(a).filter(([e,i])=>i!=null));this.config=p(p({},this.config),t)}fetch(a,t){return g(this,null,function*(){return this.config.__readOnly?u():U(this.getAPIUrl(a),p(p({keepalive:!0},t!=null?t:{}),x(this.config.apiKey)))})}getAPIUrl(a){let t="/v1/public";return new URL(`${t}${a}`,this.config.apiUrl.replace(t,"")).toString()}getGlobalState(){let a=I(this.config);if(!h[a])throw new Error("Frigade not initialized");return h[a]}};var w=class extends F{constructor({config:t,id:e}){super(t);this._isVisible=!1;this.lastStepUpdate=new Map;this.id=e,this.init()}get isVisible(){return this._isVisible===!1?!1:this.getGlobalState().rulesGraph.isFlowVisible(this.id)}set isVisible(t){this._isVisible=t}reload(){this.init()}resyncState(t){var i,s;let e=t!=null?t:this.getStatefulFlow();this.rawData=e,this.title=(i=e==null?void 0:e.data)==null?void 0:i.title,this.subtitle=(s=e==null?void 0:e.data)==null?void 0:s.subtitle,this.isCompleted=e.$state.completed,this.isStarted=e.$state.started,this.isSkipped=e.$state.skipped,this._isVisible=e.$state.visible,e.data.steps.forEach((l,r)=>{var f;let n=this.initStepFromStatefulStep(l,r),c=(f=this.steps)==null?void 0:f.get(l.id);c&&(c.$state=n.$state)})}initStepFromStatefulStep(t,e){return y(p({},t),{flow:this,$state:y(p({},t.$state),{lastActionAt:t.$state.lastActionAt?new Date(t.$state.lastActionAt):void 0}),order:e})}init(){let t=this.getStatefulFlow();this.resyncState();let e=new Map;t.data.steps.forEach((i,s)=>{let l=this.initStepFromStatefulStep(i,s);l.start=r=>g(this,null,function*(){let n=this.steps.get(i.id);if(this.getCurrentStep().id===n.id&&n.$state.started)return;let c=b(this.getGlobalState().flowStates[this.id]);c.data.steps[n.order].$state.started=!0,c.data.steps[n.order].$state.lastActionAt=new Date,c.$state.lastActionAt=new Date,c.$state.currentStepId=n.id,c.$state.currentStepIndex=n.order,this.getGlobalState().flowStates[this.id]=c,this.resyncState(),n.$state.completed||(yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:n.id,data:r!=null?r:{},createdAt:r!=null&&r.createdAt?new Date(r.createdAt):new Date().toISOString(),actionType:J})}),yield this.refreshStateFromAPI())}),l.complete=r=>g(this,null,function*(){let n=this.steps.get(i.id);if(n.$state.completed)return;let f=this.getNumberOfCompletedSteps()+1==this.steps.size,d=b(this.getGlobalState().flowStates[this.id]);d.$state.started=!0,d.data.steps[n.order].$state.completed=!0,d.data.steps[n.order].$state.started=!0,d.data.steps[n.order].$state.lastActionAt=new Date,f&&(d.$state.completed=!0);let S=Array.from(this.steps.keys())[s+1];S&&(d.$state.currentStepId=S,d.data.steps[s+1].$state.started=!0,d.data.steps[s+1].$state.lastActionAt=new Date),this.getGlobalState().flowStates[this.id]=d,this.resyncState(),f&&this.optimisticallyMarkFlowCompleted(),yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:n.id,data:r!=null?r:{},createdAt:r!=null&&r.createdAt?new Date(r.createdAt):new Date().toISOString(),actionType:K})}),yield this.refreshStateFromAPI()}),l.reset=()=>g(this,null,function*(){let r=this.steps.get(i.id);if(!r.$state.completed)return;let n=b(this.getGlobalState().flowStates[this.id]);n.data.steps[r.order].$state.started=!1,n.data.steps[r.order].$state.completed=!1,n.data.steps[r.order].$state.lastActionAt=void 0,this.getGlobalState().flowStates[this.id]=n,this.resyncState(),yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:r.id,data:{},createdAt:new Date().toISOString(),actionType:L})}),yield this.refreshStateFromAPI()}),l.onStateChange=r=>{let n=c=>{if(c.id!==this.id)return;let f=c.steps.get(i.id),d=this.lastStepUpdate.get(r);(f.$state.completed!==(d==null?void 0:d.$state.completed)||f.$state.started!==(d==null?void 0:d.$state.started)||f.$state.visible!==(d==null?void 0:d.$state.visible)||f.$state.blocked!==(d==null?void 0:d.$state.blocked))&&(r(f,d!=null?d:b(f)),this.lastStepUpdate.set(r,b(f)))};this.getGlobalState().onStepStateChangeHandlerWrappers.set(r,n),this.getGlobalState().onFlowStateChangeHandlers.push(n)},l.removeStateChangeHandler=r=>{let n=this.getGlobalState().onStepStateChangeHandlerWrappers.get(r);n&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(c=>c!==n))},e.set(i.id,l)}),this.steps=e,this.getGlobalState().variables&&this.getGlobalState().variables[this.id]&&Object.keys(this.getGlobalState().variables[this.id]).length>0&&this.applyVariables(this.getGlobalState().variables[this.id])}start(t){return g(this,null,function*(){if(this.isStarted||this.isCompleted)return;let e=b(this.getGlobalState().flowStates[this.id]);e.$state.started=!0,this.getGlobalState().flowStates[this.id]=e,this.resyncState(),yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t!=null?t:{},createdAt:new Date().toISOString(),actionType:W})}),yield this.refreshStateFromAPI()})}complete(t){return g(this,null,function*(){this.isCompleted||(this.optimisticallyMarkFlowCompleted(),yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t!=null?t:{},createdAt:t!=null&&t.createdAt?new Date(t.createdAt):new Date().toISOString(),actionType:H})}),yield this.refreshStateFromAPI())})}skip(t){return g(this,null,function*(){this.isSkipped||(this.optimisticallyMarkFlowSkipped(),yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:this.getCurrentStep().id,data:t!=null?t:{},createdAt:t!=null&&t.createdAt?new Date(t.createdAt):new Date().toISOString(),actionType:M})}),yield this.refreshStateFromAPI())})}forward(t){return g(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()+1);e&&(yield e.start(t))})}back(t){return g(this,null,function*(){let e=this.getStepByIndex(this.getCurrentStepIndex()-1);e&&(yield e.start(t))})}restart(){return g(this,null,function*(){yield this.fetch("/flowResponses",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,flowSlug:this.id,stepId:"unknown",data:{},createdAt:new Date().toISOString(),actionType:V})}),yield this.refreshStateFromAPI()})}getStepByIndex(t){return this.steps.get(Array.from(this.steps.keys())[t])}getCurrentStep(){let t=Array.from(this.steps.keys()).find(i=>this.steps.get(i).$state.completed===!1&&this.steps.get(i).$state.visible!==!1);Array.from(this.steps.keys()).forEach(i=>{var s,l;this.steps.get(i).$state.started&&this.steps.get(i).$state.lastActionAt&&this.steps.get(i).$state.lastActionAt>((l=(s=this.steps.get(t))==null?void 0:s.$state.lastActionAt)!=null?l:new Date(0))&&(t=i)});let e=t!=null?t:Array.from(this.steps.keys())[0];return this.steps.get(e)}getCurrentStepIndex(){let t=this.getCurrentStep();return Array.from(this.steps.keys()).indexOf(t.id)}getNumberOfCompletedSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.completed).length}getNumberOfAvailableSteps(){return Array.from(this.steps.values()).filter(t=>t.$state.visible).length}onStateChange(t){let e=(i,s)=>{(i.id===this.id&&(i.isCompleted!==(s==null?void 0:s.isCompleted)||i.isStarted!==(s==null?void 0:s.isStarted)||i.isSkipped!==(s==null?void 0:s.isSkipped)||i.isVisible!==(s==null?void 0:s.isVisible))||JSON.stringify(i.steps)!==JSON.stringify(s==null?void 0:s.steps))&&t(i,s)};this.getGlobalState().onFlowStateChangeHandlerWrappers.set(t,e),this.getGlobalState().onFlowStateChangeHandlers.push(e)}removeStateChangeHandler(t){let e=this.getGlobalState().onFlowStateChangeHandlerWrappers.get(t);e&&(this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(i=>i!==e))}applyVariables(t){var i,s;let e=l=>{let r=l.match(/\${(.*?)}/g);return r&&r.forEach(n=>{let c=n.replace("${","").replace("}","");t[c]&&(l=l.replace(n,t[c]))}),l};this.title=e((i=this.title)!=null?i:""),this.subtitle=e((s=this.subtitle)!=null?s:""),this.steps.forEach(l=>{Object.keys(l).forEach(r=>{typeof l[r]=="string"&&(l[r]=e(l[r]))})}),this.getGlobalState().variables={},this.getGlobalState().variables[this.id]=t}getStatefulFlow(){return this.getGlobalState().flowStates[this.id]}refreshStateFromAPI(){return g(this,null,function*(){yield this.getGlobalState().refreshStateFromAPI(),this.resyncState()})}optimisticallyMarkFlowCompleted(){let t=b(this.getGlobalState().flowStates[this.id]);t.$state.completed=!0,t.$state.started=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}optimisticallyMarkFlowSkipped(){let t=b(this.getGlobalState().flowStates[this.id]);t.$state.skipped=!0,t.$state.visible=!1,this.getGlobalState().flowStates[this.id]=t,this.resyncState()}register(t){this.getGlobalState().rulesGraph.register(this.id,t)}unregister(){this.getGlobalState().rulesGraph.unregister(this.id)}};var L="NOT_STARTED_STEP",H="COMPLETED_FLOW",M="SKIPPED_FLOW",W="STARTED_FLOW",V="NOT_STARTED_FLOW",K="COMPLETED_STEP",J="STARTED_STEP",ot="frigade-last-call-at-",nt="frigade-last-call-data-",B="frigade-guest-key",R="guest_",lt="get-cache-";var dt=1e3,v="fr-js-";function C(o){return new w({config:o.config,id:o.id})}function b(o){return JSON.parse(JSON.stringify(o))}function x(o){return{headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","X-Frigade-SDK-Version":N,"X-Frigade-SDK-Platform":"Javascript"}}}function E(o){return m()?window.localStorage.getItem(`${v}${o}`):null}function O(o,a){m()&&window.localStorage.setItem(`${v}${o}`,a)}function _(){Object.keys(h).forEach(o=>{o.startsWith(lt)&&delete h[o]})}function j(){m()&&Object.keys(window.localStorage).forEach(o=>{o.startsWith(v)&&window.localStorage.removeItem(o)})}function U(o,a){return g(this,null,function*(){let t=ot+o,e=nt+o;if(m()&&a&&a.body&&a.method==="POST"){let s=E(t),l=E(e);if(s&&l&&l==a.body){let r=new Date(s);if(new Date().getTime()-r.getTime()<dt)return u()}O(t,new Date().toISOString()),O(e,a.body),_()}let i;try{i=at(o,a),i=yield i}catch(s){return u(s)}if(!i)return u("Received an empty response");if(i.status>=400)return u(i.statusText);try{if(i.status===204||i.status===201)return u();let s=yield i.json();return s.error?u(s.error):s}catch(s){return u(s)}})}function u(o){return o&&console.log("Call to Frigade failed",o),{json:()=>({})}}function k(){if(m()){let o=E(B);return o||(o=`${R}${rt()}`,O(B,o)),o}}function m(){return typeof window!="undefined"&&typeof window.document!="undefined"&&typeof window.localStorage!="undefined"}var A=class{constructor(a,t){this.graph=new Map;this.registry=new Map;this._rawGraphData=a,t&&(this.registry=t),this.ingestGraphData(a)}get rawGraphData(){return this._rawGraphData}ingestGraphData(a){this.graph=new Map(Object.entries(a)),this.fireCallbacks()}fireCallbacks(){for(let[a,t]of this.registry)typeof t=="function"&&t(this.isFlowVisible(a))}isFlowVisible(a){let t=this.graph.get(a);return t?t.visible===!1?!1:t.edges.length===0?!0:this.findRegisteredDescendant(a)==null:!0}register(a,t){this.registry.set(a,t),this.fireCallbacks()}unregister(a){this.registry.delete(a),this.fireCallbacks()}getRegistry(){return this.registry}findRegisteredDescendant(a,t=a,e){let i=this.graph.get(a);if(i==null)return;if(this.registry.has(a)&&t!==a)return i;let s;if(i.edges.length>0)for(let l of i.edges){if(e!=null&&l.ruleId!==e)continue;let r=this.findRegisteredDescendant(l.head,t,e!=null?e:l.ruleId);if(r!=null&&r.visible){s=r;break}}return s}};var P=class extends F{constructor(t,e){super(p({apiKey:t},e));this.flows=[];this.hasFailed=!1;this.visibilityChangeHandler=()=>g(this,null,function*(){document.visibilityState==="visible"&&(yield this.refreshStateFromAPI())});this.init(this.config),m()&&document.addEventListener("visibilitychange",this.visibilityChangeHandler)}destroy(){if(m()){document.removeEventListener("visibilitychange",this.visibilityChangeHandler);let t=I(this.config);h[t]&&(h[t].onFlowStateChangeHandlers=[])}}init(t){return g(this,null,function*(){return this.config=p(p({},this.config),t),this.initPromise=(()=>g(this,null,function*(){var e;this.config.userId&&!((e=this.config.userId)!=null&&e.startsWith(R))&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId})})),yield this.refreshStateFromAPI()}))(),this.initPromise})}identify(t,e){return g(this,null,function*(){this.config=y(p({},this.config),{userId:t}),yield this.initIfNeeded(),yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,properties:e})}),yield this.resync()})}group(t,e){return g(this,null,function*(){yield this.initIfNeeded(),this.config.groupId=t,yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,properties:e})}),yield this.resync()})}track(t,e){return g(this,null,function*(){if(yield this.initIfNeeded(),!t){console.error("Event name is required to track an event");return}this.config.userId&&this.config.groupId?yield this.fetch("/userGroups",{method:"POST",body:JSON.stringify({foreignUserId:this.config.userId,foreignUserGroupId:this.config.groupId,events:[{event:t,properties:e}]})}):this.config.userId&&(yield this.fetch("/users",{method:"POST",body:JSON.stringify({foreignId:this.config.userId,events:[{event:t,properties:e}]})})),yield this.resync()})}isReady(){return!!(this.config.__instanceId&&this.config.apiKey&&this.initPromise)}getFlow(t){return g(this,null,function*(){return yield this.initIfNeeded(),this.flows.find(e=>e.id==t)})}getFlows(){return g(this,null,function*(){return yield this.initIfNeeded(),this.flows})}reload(){return g(this,null,function*(){j(),_(),yield this.refreshStateFromAPI(),this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,C(t))})})})}resync(){return g(this,null,function*(){this.initPromise=null,yield this.init(this.config),this.flows.forEach(t=>{this.getGlobalState().onFlowStateChangeHandlers.forEach(e=>{let i=this.getGlobalState().previousFlows.get(t.id);e(t,i),this.getGlobalState().previousFlows.set(t.id,C(t))})})})}onStateChange(t){return g(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers.push(t)})}hasFailedToLoad(){return this.hasFailed}removeStateChangeHandler(t){return g(this,null,function*(){yield this.initIfNeeded(),this.getGlobalState().onFlowStateChangeHandlers=this.getGlobalState().onFlowStateChangeHandlers.filter(e=>e!==t)})}initIfNeeded(){return g(this,null,function*(){return this.initPromise!==null?this.initPromise:this.init(this.config)})}refreshStateFromAPI(){return g(this,null,function*(){let t=I(this.config);if(!h[t]){let e=this,i={set:function(s,l,r){if(s[l]){let n=s[l],c=r;JSON.stringify(n)!==JSON.stringify(c)&&e.triggerEventHandlers(c,n)}return s[l]=r,!0}};if(h[t]={refreshStateFromAPI:()=>g(this,null,function*(){}),rulesGraph:new A({}),flowStates:new Proxy({},i),onFlowStateChangeHandlerWrappers:new Map,onStepStateChangeHandlerWrappers:new Map,onFlowStateChangeHandlers:[],previousFlows:new Map,variables:{}},this.config.__readOnly&&this.config.__flowConfigOverrides){this.mockFlowStates(t);return}h[t].refreshStateFromAPI=()=>g(this,null,function*(){var r,n,c,f,d;if(this.config.__readOnly)return;let s=yield this.fetch(`/flowStates?userId=${encodeURIComponent(this.config.userId)}${this.config.groupId?`&groupId=${encodeURIComponent(this.config.groupId)}`:""}`),l=JSON.stringify(h[t].rulesGraph.rawGraphData)!==JSON.stringify((r=s.ruleGraph)==null?void 0:r.graph);h[t].rulesGraph=new A((c=(n=s.ruleGraph)==null?void 0:n.graph)!=null?c:{},(d=(f=h[t])==null?void 0:f.rulesGraph)==null?void 0:d.getRegistry()),l&&this.flows.forEach(S=>{var T;if((T=s.ruleGraph)!=null&&T.graph[S.id]){let q=s.eligibleFlows.find(G=>G.flowSlug===S.id),Q=this.getGlobalState().previousFlows.get(S.id);S.resyncState(q),this.getGlobalState().onFlowStateChangeHandlers.forEach(G=>{G(S,Q),this.getGlobalState().previousFlows.set(S.id,C(S))})}}),s&&s.eligibleFlows?(s.eligibleFlows.forEach(S=>{h[t].flowStates[S.flowSlug]=S,this.flows.find(T=>T.id==S.flowSlug)||this.flows.push(new w({config:this.config,id:S.flowSlug}))}),this.hasFailed=!1):this.hasFailed=!0})}yield h[t].refreshStateFromAPI()})}mockFlowConfigs(){Object.keys(this.config.__flowConfigOverrides).forEach(t=>{this.flows.push(new w({config:this.config,id:t}))})}mockFlowStates(t){Object.keys(this.config.__flowConfigOverrides).forEach(e=>{var s,l,r;let i=JSON.parse(this.config.__flowConfigOverrides[e]);h[t].flowStates[e]={flowSlug:e,flowName:(s=i==null?void 0:i.name)!=null?s:e,flowType:(l=i==null?void 0:i.type)!=null?l:"CHECKLIST",data:y(p({},i),{steps:((r=i==null?void 0:i.steps)!=null?r:[]).map(n=>p({id:n.id,$state:{completed:!1,started:!1,visible:!0,blocked:!1}},n))}),$state:{currentStepId:null,currentStepIndex:-1,completed:!1,started:!1,skipped:!1,visible:!0}},this.flows.push(new w({config:this.config,id:e}))})}triggerEventHandlers(t,e){return g(this,null,function*(){t&&this.flows.forEach(i=>{i.id==e.flowSlug&&this.getGlobalState().onFlowStateChangeHandlers.forEach(s=>{let l=this.getGlobalState().previousFlows.get(i.id);i.resyncState(t),s(i,l),this.getGlobalState().previousFlows.set(i.id,C(i))})})})}};var X=(t=>(t.MANUAL="MANUAL",t.AUTOMATIC="AUTOMATIC",t))(X||{}),Y=(e=>(e.DRAFT="DRAFT",e.ACTIVE="ACTIVE",e.ARCHIVED="ARCHIVED",e))(Y||{}),z=(d=>(d.ANNOUNCEMENT="ANNOUNCEMENT",d.CHECKLIST="CHECKLIST",d.FORM="FORM",d.TOUR="TOUR",d.SUPPORT="SUPPORT",d.CUSTOM="CUSTOM",d.BANNER="BANNER",d.EMBEDDED_TIP="EMBEDDED_TIP",d.NPS_SURVEY="NPS_SURVEY",d.SURVEY="SURVEY",d.CARD="CARD",d))(z||{});export{w as Flow,Y as FlowStatus,z as FlowType,P as Frigade,X as TriggerType};
3
3
  //# sourceMappingURL=index.js.map