@onlive.ai/flow-client 0.1.38 → 0.1.44

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.
@@ -1,908 +1,2 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
-
5
- // client/client.service.spec.ts
6
- import { beforeEach, describe, expect, it, vi } from "vitest";
7
- import { ZodError } from "zod";
8
-
9
- // client/client.service.ts
10
- import { merge as merge2 } from "@onlive.ai/common-121/utils/merge.js";
11
-
12
- // tracking/tracking.service.ts
13
- import { Session, Tracker } from "@onlive.ai/tracker";
14
- import { merge } from "@onlive.ai/common-121/utils/merge.js";
15
- import { browserPreferences } from "@onlive.ai/common-121/utils/browser-preferences.js";
16
-
17
- // tracking/tracking.types.ts
18
- import { z } from "zod";
19
- var ONLIVE_FLOW_FORM_NAME = "flow_form";
20
- var ONLIVE_ANALYTICS_EVENT = "onlive-analytics-event";
21
- var TrackingOptionsSchema = z.object({
22
- enabled: z.boolean().default(false).optional(),
23
- data: z.custom().optional(),
24
- removeExtraneousValues: z.boolean().default(true).optional(),
25
- allowBotTraffic: z.boolean().default(false).optional(),
26
- adapters: z.array(z.string()).default([]).optional(),
27
- apiUrl: z.string().url().optional(),
28
- emitters: z.object({
29
- windowEvent: z.boolean().optional(),
30
- dataLayer: z.boolean().optional(),
31
- windowPostMessage: z.boolean().optional()
32
- }).optional()
33
- });
34
-
35
- // tracking/tracking.service.ts
36
- var TrackingService = class {
37
- /**
38
- * Creates a new TrackingService instance.
39
- * @param organizationId - The ID of the organization
40
- * @param flowId - The ID of the flow being tracked
41
- * @param options - Configuration options for the tracking service
42
- * @param devMode - Flag indicating whether to run in development mode
43
- */
44
- constructor(organizationId, flowId, options, devMode) {
45
- /**
46
- * Configuration options for the tracking service.
47
- */
48
- __publicField(this, "options");
49
- /**
50
- * The tracker instance used to send events.
51
- */
52
- __publicField(this, "tracker");
53
- /**
54
- * List of event listeners for tracking events.
55
- */
56
- __publicField(this, "eventListeners", []);
57
- this.options = TrackingOptionsSchema.parse(options);
58
- this.tracker = new Tracker({
59
- apiUrl: this.options.apiUrl,
60
- removeExtraneousValues: this.options.removeExtraneousValues,
61
- allowBotTraffic: this.options.allowBotTraffic,
62
- adapters: this.options.adapters,
63
- dryRun: devMode
64
- });
65
- this.tracker.setBase(
66
- merge(
67
- {},
68
- {
69
- organization_id: organizationId,
70
- page_url: window.location.href,
71
- page_referrer: document.referrer,
72
- origin_medium: "web",
73
- guest_id: Session.id,
74
- interaction_id: Session.interactionId,
75
- extra: {
76
- flow_id: flowId
77
- }
78
- },
79
- this.options.data
80
- )
81
- );
82
- window.addEventListener(
83
- ONLIVE_ANALYTICS_EVENT,
84
- ({ detail }) => this.emit(detail.event, detail.data)
85
- );
86
- }
87
- /**
88
- * Returns the tracker instance used for sending events.
89
- * @returns {Tracker} The tracker instance
90
- */
91
- getTracker() {
92
- return this.tracker;
93
- }
94
- /**
95
- * Returns tracking-related user preferences and session information.
96
- *
97
- * This method combines browser preferences with session identification data
98
- * that can be used for tracking and analytics purposes.
99
- *
100
- * @returns {Object} An object containing browser preferences and session identifiers
101
- * @property {string} interactionId - The current session interaction identifier
102
- * @property {string} guestId - The unique identifier for the current guest/user
103
- */
104
- preferences() {
105
- return {
106
- ...browserPreferences(),
107
- interactionId: Session.interactionId,
108
- guestId: Session.id
109
- };
110
- }
111
- /**
112
- * Analyzes a request and generates tracking events based on the provided trigger and options.
113
- *
114
- * @param {GetStepTrigger | { stepId?: string }} trigger - The trigger for the step, which can be either a `GetStepTrigger` or an object containing an optional `stepId`.
115
- * @param {GetStepOptions} options - The options for getting the step, including fields for form data.
116
- */
117
- analyzeRequest(trigger, options) {
118
- if ("currentStepId" in trigger) {
119
- if (trigger.actionId) {
120
- this.tracker.send("element_click", {
121
- element_label: trigger.actionId,
122
- element_type: "button",
123
- form_name: Object.keys(options.fields || {}).length ? ONLIVE_FLOW_FORM_NAME : void 0,
124
- step_name: trigger.currentStepId
125
- });
126
- }
127
- if (options.fields) {
128
- this.tracker.send("form_submit", {
129
- form_name: ONLIVE_FLOW_FORM_NAME,
130
- form_data: options.fields,
131
- step_name: trigger.currentStepId
132
- });
133
- }
134
- }
135
- }
136
- /**
137
- * Analyzes the response based on the provided trigger and flow context, and generates tracking events.
138
- *
139
- * @param {GetStepTrigger | { stepId?: string }} trigger - The trigger for the step, which can be either a `GetStepTrigger` or an object containing an optional `stepId`.
140
- * @param {FlowContext} flowContext - The context of the flow, containing information about the current step and its result.
141
- */
142
- analyzeResponse(trigger, flowContext) {
143
- if ("currentStepId" in trigger) {
144
- if (flowContext.step.result?.pipelines) {
145
- flowContext.step.result.pipelines.forEach((pipeline) => {
146
- this.tracker.send("task_success", {
147
- task_name: pipeline.name,
148
- task_data: pipeline.data,
149
- step_name: flowContext.step.id
150
- });
151
- });
152
- }
153
- if (flowContext.step.error) {
154
- this.tracker.send("form_error", {
155
- form_name: ONLIVE_FLOW_FORM_NAME,
156
- form_error: flowContext.step.error.code,
157
- step_name: flowContext.step.id
158
- });
159
- }
160
- }
161
- this.tracker.send("impression", {
162
- impression_type: "step",
163
- form_name: void 0,
164
- step_name: flowContext.step.id,
165
- step_initial: !("currentStepId" in trigger) || void 0,
166
- step_final: flowContext.step.isFinal
167
- });
168
- this.tracker.setBase({
169
- form_name: ONLIVE_FLOW_FORM_NAME,
170
- step_name: flowContext.step.id,
171
- step_initial: !("currentStepId" in trigger) || void 0,
172
- step_final: flowContext.step.isFinal,
173
- ...flowContext.step.result?.tracking
174
- });
175
- }
176
- /**
177
- * Sends an event to the tracker.
178
- *
179
- * This method dispatches an event with the provided name and data to the tracking system.
180
- * Events represent user interactions or system occurrences that should be recorded for analytics.
181
- *
182
- * @param eventName - The name of the event to send
183
- * @param eventData - The data associated with the event
184
- */
185
- send(eventName, eventData) {
186
- this.tracker.send(eventName, eventData);
187
- }
188
- /**
189
- * Sets base data for the tracker that will be included in all future events.
190
- *
191
- * This method defines default properties that will be automatically included
192
- * in every tracking event sent after this call. This is useful for setting
193
- * context information that remains constant across multiple events.
194
- *
195
- * @param data - The base data to set for the tracker
196
- */
197
- setData(data) {
198
- this.tracker.setBase(data);
199
- }
200
- /**
201
- * Registers an event listener to be notified when tracking events are emitted.
202
- *
203
- * @param {function} listener - The callback function to execute when an event is emitted
204
- */
205
- onEvent(listener) {
206
- this.eventListeners.push(listener);
207
- }
208
- /**
209
- * Emits an event to all registered listeners for the specified event name.
210
- *
211
- * @param {EventName} eventName - The name of the event to emit
212
- * @param {EventData} eventData - The data associated with the event
213
- */
214
- emit(eventName, eventData) {
215
- this.eventListeners.forEach((listener) => listener({ event: eventName, data: eventData }));
216
- }
217
- };
218
- var tracking_service_default = TrackingService;
219
-
220
- // client/client.types.ts
221
- import { GetAvailabilityFilters, GetAvailabilityOptions } from "@onlive.ai/calendar";
222
- import { z as z2 } from "zod";
223
- var DEFAULT_CLIENT_OPTIONS = {
224
- tracking: {
225
- removeExtraneousValues: true,
226
- apiUrl: "https://srvless.onlive.site/tracking",
227
- data: {
228
- widget_type: "OnliveAppFlow"
229
- }
230
- }
231
- };
232
- var StepId = z2.string().nonempty();
233
- var ClientOptions = z2.object({
234
- baseUrl: z2.string().url().nonempty(),
235
- flowId: z2.string().length(24).nonempty(),
236
- organizationId: z2.string().uuid().nonempty(),
237
- lang: z2.string().length(2).nonempty(),
238
- tracking: TrackingOptionsSchema.optional(),
239
- devMode: z2.boolean().default(false).optional()
240
- });
241
- var GetStepOptions = z2.object({
242
- state: z2.record(z2.string(), z2.any()).optional(),
243
- fields: z2.record(z2.string(), z2.any()).optional()
244
- });
245
- var GetStepTrigger = z2.object({
246
- currentStepId: z2.string().nonempty(),
247
- actionId: z2.string().nonempty()
248
- });
249
- var FieldType = z2.enum([
250
- "text",
251
- "boolean",
252
- "number",
253
- "email",
254
- "phone",
255
- "mobile_phone",
256
- "date",
257
- "time",
258
- "datetime",
259
- "password",
260
- "url",
261
- "color",
262
- "object",
263
- "void",
264
- "location",
265
- "availability"
266
- ]);
267
- var LocationProperty = z2.object({
268
- name: z2.string(),
269
- value: z2.string().optional(),
270
- icon: z2.string().optional(),
271
- type: z2.enum(["url", "email", "phone"]).optional()
272
- });
273
- var Location = z2.object({
274
- lat: z2.number().min(-90).max(90),
275
- lng: z2.number().min(-180).max(180),
276
- meta: z2.record(z2.string(), z2.any()).optional(),
277
- properties: z2.record(z2.string(), LocationProperty).optional(),
278
- attributes: z2.record(z2.string(), z2.any()).optional()
279
- });
280
- var Availability = z2.object({
281
- datetime: z2.string().datetime(),
282
- meta: z2.record(z2.string(), z2.any()).optional()
283
- });
284
- var FieldValue = z2.union([z2.string(), z2.number(), z2.boolean(), Location, Availability]);
285
- var MapPin = z2.object({
286
- content: z2.object({
287
- icon: z2.string().optional(),
288
- url: z2.string().url().optional(),
289
- width: z2.string().optional(),
290
- height: z2.string().optional(),
291
- scale: z2.number().optional()
292
- }).optional(),
293
- background: z2.string().optional(),
294
- glyph: z2.object({
295
- color: z2.string().optional(),
296
- url: z2.string().url().optional(),
297
- icon: z2.string().optional()
298
- }).optional(),
299
- borderColor: z2.string().optional(),
300
- scale: z2.number().optional()
301
- });
302
- var FormatDateString = z2.custom((val) => /^\d{4}-\d{2}-\d{2}$/.test(val), {
303
- message: "Date must be in 'YYYY-MM-DD' format"
304
- });
305
- var AffixSlot = z2.object({
306
- text: z2.string().optional(),
307
- icon: z2.string().optional()
308
- });
309
- var Field = z2.object({
310
- name: z2.string().nonempty(),
311
- label: z2.string().optional(),
312
- value: z2.union([FieldValue, z2.array(FieldValue)]).optional(),
313
- type: FieldType,
314
- component: z2.enum([
315
- "input",
316
- "textarea",
317
- "select",
318
- "radio",
319
- "checkbox",
320
- "switch",
321
- "rating",
322
- "carousel",
323
- "button",
324
- "label",
325
- "map",
326
- "calendar"
327
- ]).optional(),
328
- disabled: z2.boolean().optional(),
329
- readonly: z2.boolean().optional(),
330
- multiple: z2.boolean().optional(),
331
- placeholder: z2.string().optional(),
332
- options: z2.array(
333
- z2.object({
334
- label: z2.string().nonempty(),
335
- value: FieldValue.optional(),
336
- image: z2.string().url().optional(),
337
- description: z2.string().optional(),
338
- disabled: z2.boolean().optional()
339
- })
340
- ).optional(),
341
- required: z2.boolean().optional(),
342
- configuration: z2.object({
343
- input: z2.object({
344
- min: z2.number().optional(),
345
- max: z2.number().optional(),
346
- step: z2.number().optional(),
347
- pattern: z2.string().refine((val) => {
348
- try {
349
- new RegExp(val);
350
- return true;
351
- } catch {
352
- return false;
353
- }
354
- }, "Invalid regex pattern").optional(),
355
- minLength: z2.number().optional(),
356
- maxLength: z2.number().optional(),
357
- exactLength: z2.number().optional(),
358
- prefix: z2.object({
359
- default: AffixSlot.optional(),
360
- success: AffixSlot.optional(),
361
- error: AffixSlot.optional()
362
- }).optional(),
363
- suffix: z2.object({
364
- default: AffixSlot.optional(),
365
- success: AffixSlot.optional(),
366
- error: AffixSlot.optional()
367
- }).optional(),
368
- clearable: z2.boolean().optional(),
369
- floatingLabel: z2.boolean().optional()
370
- }).optional(),
371
- textarea: z2.object({
372
- rows: z2.number().optional()
373
- }).optional(),
374
- checkbox: z2.object({
375
- layout: z2.enum(["horizontal", "vertical"])
376
- }).optional(),
377
- rating: z2.object({
378
- icons: z2.array(z2.string()).optional(),
379
- color: z2.string().optional(),
380
- precision: z2.number().optional()
381
- }).optional(),
382
- map: z2.object({
383
- apiKey: z2.string().optional(),
384
- region: z2.string().length(2).optional(),
385
- center: z2.object({
386
- lat: z2.number().min(-90).max(90),
387
- lng: z2.number().min(-180).max(180)
388
- }).optional(),
389
- showMap: z2.enum(["always", "on-search"]).optional(),
390
- zoom: z2.object({
391
- initial: z2.number().optional(),
392
- focus: z2.number().optional(),
393
- max: z2.number().optional(),
394
- min: z2.number().optional()
395
- }).optional(),
396
- controls: z2.object({
397
- fullscreen: z2.boolean().optional(),
398
- mapType: z2.boolean().optional(),
399
- zoom: z2.boolean().optional(),
400
- rotate: z2.boolean().optional(),
401
- scale: z2.boolean().optional(),
402
- streetView: z2.boolean().optional()
403
- }).optional(),
404
- initialLocations: z2.number().optional(),
405
- maxLocations: z2.number().optional(),
406
- distanceUnit: z2.enum(["km", "mi"]).optional(),
407
- distanceFormat: z2.enum(["short", "long"]).optional(),
408
- options: z2.object({
409
- show: z2.enum(["always", "on-search", "never"]).optional(),
410
- component: z2.enum(["list-button", "list-radio", "carousel"]).optional(),
411
- searchLabel: z2.string().optional(),
412
- detailsLabel: z2.string().optional()
413
- }).optional(),
414
- search: z2.object({
415
- value: z2.string().optional(),
416
- button: z2.object({
417
- label: z2.string().optional(),
418
- position: z2.enum(["inside", "outside"]).optional()
419
- }).optional(),
420
- placeholder: z2.string().optional(),
421
- noResultsText: z2.string().optional(),
422
- autocomplete: z2.boolean().optional(),
423
- clearable: z2.boolean().optional(),
424
- mode: z2.enum(["address", "postcode"]).optional(),
425
- showLocationButton: z2.boolean().optional(),
426
- locationButton: z2.object({
427
- icon: z2.string().optional(),
428
- position: z2.enum(["left", "right"]).optional()
429
- }).optional()
430
- }).optional(),
431
- distanceRange: z2.object({
432
- initial: z2.number().optional(),
433
- min: z2.number().optional(),
434
- max: z2.number().optional(),
435
- step: z2.number().optional()
436
- }).optional(),
437
- mapRegion: z2.object({
438
- strokeColor: z2.string().optional(),
439
- fillColor: z2.string().optional(),
440
- fillOpacity: z2.number().optional()
441
- }).optional(),
442
- locationPin: MapPin.optional(),
443
- markerPin: z2.object({
444
- default: MapPin.optional(),
445
- hover: MapPin.optional(),
446
- selected: MapPin.optional()
447
- }).optional(),
448
- infoWindow: z2.object({
449
- button: z2.object({
450
- label: z2.string(),
451
- action: z2.string()
452
- }).optional()
453
- }).optional()
454
- }).optional(),
455
- calendar: z2.object({
456
- current: z2.object({
457
- month: z2.number().min(0).max(11).optional(),
458
- year: z2.number().optional()
459
- }).optional(),
460
- range: z2.object({
461
- min: FormatDateString.optional(),
462
- max: FormatDateString.optional(),
463
- enabled: z2.array(FormatDateString).optional(),
464
- disabled: z2.array(FormatDateString).optional()
465
- }).optional(),
466
- time: z2.object({
467
- label: z2.string().optional(),
468
- format: z2.enum(["12h", "24h"]).optional(),
469
- component: z2.enum(["carousel", "list"]).optional()
470
- }).optional(),
471
- api: z2.object({
472
- url: z2.string().url().nonempty(),
473
- organizationId: z2.string().nonempty(),
474
- availability: z2.object({
475
- filters: GetAvailabilityFilters,
476
- options: GetAvailabilityOptions.optional()
477
- }).optional()
478
- }).optional()
479
- }).optional()
480
- }).optional(),
481
- dependsOn: z2.array(
482
- z2.object({
483
- fieldName: z2.string().nonempty(),
484
- value: FieldValue.optional()
485
- })
486
- ).optional(),
487
- dependentBehavior: z2.enum(["hidden", "disabled"]).optional(),
488
- customError: z2.object({
489
- required: z2.string().optional(),
490
- invalid: z2.string().optional(),
491
- minLength: z2.string().optional(),
492
- maxLength: z2.string().optional(),
493
- minValue: z2.string().optional(),
494
- maxValue: z2.string().optional(),
495
- mismatch: z2.string().optional()
496
- }).optional()
497
- });
498
- var ActionScript = z2.object({
499
- src: z2.string().url(),
500
- preload: z2.boolean().optional(),
501
- name: z2.string().nonempty(),
502
- function: z2.string().nonempty(),
503
- params: z2.record(z2.string(), z2.any()).optional()
504
- });
505
- var ActionEvent = z2.object({
506
- name: z2.enum(["organization_call", "close_panel"]),
507
- params: z2.record(z2.string(), z2.any()).optional()
508
- });
509
- var Action = z2.object({
510
- id: z2.string().nonempty(),
511
- type: z2.enum(["submit", "navigate", "link", "back", "dispatcher", "script"]),
512
- label: z2.string().nonempty(),
513
- variant: z2.enum(["primary", "secondary", "success", "danger", "warning", "info"]),
514
- url: z2.string().url().optional(),
515
- scripts: ActionScript.array().optional(),
516
- events: ActionEvent.array().optional()
517
- });
518
- var ErrorCode = z2.enum([
519
- "INVALID_DATA",
520
- "INVALID_ACTION",
521
- "STEP_NOT_FOUND",
522
- "UNKNOWN_ERROR",
523
- "APPOINTMENT_INVALID_DATA",
524
- "APPOINTMENT_BUSY_SLOT",
525
- "APPOINTMENT_OUT_OF_DATE",
526
- "APPOINTMENT_UNKNOWN_ERROR",
527
- "LEAD_INVALID_DATA",
528
- "LEAD_UNKNOWN_ERROR",
529
- "CONTENT_INVALID_DATA",
530
- "CONTENT_UNKNOWN_ERROR",
531
- "CONTACT_INVALID_DATA",
532
- "CONTACT_UNKNOWN_ERROR",
533
- "LOST_OPPORTUNITY_INVALID_DATA",
534
- "LOST_OPPORTUNITY_UNKNOWN_ERROR"
535
- ]);
536
- var PostAction = z2.object({
537
- type: z2.enum(["redirect"]),
538
- params: z2.record(z2.string(), z2.any()).optional()
539
- });
540
- var Step = z2.object({
541
- id: z2.string().nonempty(),
542
- title: z2.string().optional(),
543
- description: z2.string().optional(),
544
- stageId: z2.string().optional(),
545
- state: z2.record(z2.string(), z2.any()).optional(),
546
- fields: z2.array(Field).optional(),
547
- actions: z2.array(Action).optional(),
548
- result: z2.object({
549
- postActions: z2.array(PostAction).optional(),
550
- pipelines: z2.array(z2.object({ name: z2.string(), data: z2.object({}) })).optional(),
551
- tracking: z2.record(z2.string(), z2.any()).optional()
552
- }).optional(),
553
- error: z2.object({
554
- code: ErrorCode,
555
- message: z2.string().optional(),
556
- fields: z2.array(
557
- z2.object({
558
- name: z2.string(),
559
- type: FieldType,
560
- value: z2.any(),
561
- error: z2.string()
562
- })
563
- ).optional()
564
- }).optional(),
565
- isFinal: z2.boolean().optional()
566
- });
567
- var Flow = z2.object({
568
- id: z2.string().length(24).nonempty(),
569
- organizationId: z2.string().uuid().nonempty(),
570
- updatedAt: z2.string().datetime().nonempty(),
571
- stages: z2.array(
572
- z2.object({
573
- id: z2.string().nonempty(),
574
- name: z2.string().nonempty()
575
- })
576
- )
577
- });
578
- var FlowContext = z2.object({
579
- status: z2.enum(["ok", "error"]),
580
- step: Step,
581
- flow: Flow
582
- });
583
- var EventType = z2.enum(["track"]);
584
-
585
- // client/client.service.ts
586
- var FlowClient = class {
587
- /**
588
- * Creates a new FlowClient instance.
589
- * @param _options - Configuration options for the client
590
- */
591
- constructor(_options) {
592
- /**
593
- * The base URL for API requests.
594
- */
595
- __publicField(this, "baseURL");
596
- /**
597
- * HTTP headers to be sent with each request.
598
- */
599
- __publicField(this, "headers");
600
- /**
601
- * The unique identifier of the flow.
602
- */
603
- __publicField(this, "flowId");
604
- /**
605
- * Service for tracking user interactions and events.
606
- * Only available if tracking is enabled in the options.
607
- */
608
- __publicField(this, "tracking");
609
- const options = merge2(
610
- {},
611
- DEFAULT_CLIENT_OPTIONS,
612
- ClientOptions.parse(_options)
613
- );
614
- this.flowId = options.flowId;
615
- this.baseURL = options.baseUrl;
616
- this.headers = new Headers({
617
- "Content-Type": "application/json",
618
- "X-Onlive-Organization-Id": options.organizationId,
619
- "X-Lang": options.lang
620
- });
621
- if (options.tracking?.enabled) {
622
- this.tracking = new tracking_service_default(
623
- options.organizationId,
624
- options.flowId,
625
- options.tracking,
626
- !!options.devMode
627
- );
628
- }
629
- }
630
- /**
631
- * Sends an HTTP request to the specified path and returns the response as a JSON object.
632
- *
633
- * @template T - The expected response type.
634
- * @param {string} path - The path to which the request is sent.
635
- * @param {RequestInit} [options={}] - Optional configuration for the request.
636
- * @returns {Promise<T>} - A promise that resolves to the response data.
637
- * @throws {Error} - Throws an error if the response status is not ok.
638
- */
639
- async request(path, options = {}) {
640
- const response = await fetch(`${this.baseURL}/${path}`, {
641
- ...options,
642
- headers: this.headers
643
- });
644
- if (!response?.ok) {
645
- throw new Error(`HTTP error! status: ${response?.status || "unknown"}`);
646
- }
647
- return response.json();
648
- }
649
- /**
650
- * Initiates the first step of the flow process.
651
- *
652
- * @param {GetStepOptions} options - Optional parameters for getting the step.
653
- * @returns {Promise<FlowContext>} A promise that resolves to the flow context.
654
- */
655
- async firstStep(options = {}) {
656
- this.tracking?.analyzeRequest({}, options);
657
- const preferences = this.tracking?.preferences();
658
- const flowContext = await this.request(`flow/${this.flowId}/first-step`, {
659
- method: "POST",
660
- body: JSON.stringify(
661
- GetStepOptions.parse({
662
- ...options,
663
- state: {
664
- preferences,
665
- ...options.state
666
- }
667
- })
668
- )
669
- });
670
- this.tracking?.analyzeResponse({}, flowContext);
671
- return flowContext;
672
- }
673
- /**
674
- * Retrieves a specific step in the flow based on the provided step ID.
675
- *
676
- * @param {string} stepId - The unique identifier of the step to retrieve.
677
- * @param {GetStepOptions} options - Optional parameters for customizing the step request.
678
- * @returns {Promise<FlowContext>} A promise that resolves to the flow context containing the requested step information.
679
- * @throws {Error} If the step ID is invalid or the step cannot be found.
680
- */
681
- async getStep(stepId, options = {}) {
682
- this.tracking?.analyzeRequest({ stepId }, options);
683
- const preferences = this.tracking?.preferences();
684
- const flowContext = await this.request(
685
- `flow/${this.flowId}/steps/${StepId.parse(stepId)}`,
686
- {
687
- method: "POST",
688
- body: JSON.stringify(
689
- GetStepOptions.parse({
690
- ...options,
691
- state: {
692
- preferences,
693
- ...options.state
694
- }
695
- })
696
- )
697
- }
698
- );
699
- this.tracking?.analyzeResponse({ stepId }, flowContext);
700
- return flowContext;
701
- }
702
- /**
703
- * Advances to the next step in the flow based on the provided trigger action.
704
- *
705
- * @param {GetStepTrigger} trigger - Contains the current step ID and action ID to determine the next step.
706
- * @param {GetStepOptions} options - Optional parameters to customize the step transition.
707
- * @returns {Promise<FlowContext>} A promise that resolves to the updated flow context containing the next step information.
708
- * @throws {Error} If the action is invalid or the next step cannot be determined.
709
- */
710
- async nextStep(trigger, options = {}) {
711
- this.tracking?.analyzeRequest(trigger, options);
712
- const { currentStepId, actionId } = GetStepTrigger.parse(trigger);
713
- const flowContext = await this.request(
714
- `flow/${this.flowId}/steps/${currentStepId}/action/${actionId}`,
715
- {
716
- method: "POST",
717
- body: JSON.stringify(GetStepOptions.parse(options))
718
- }
719
- );
720
- this.tracking?.analyzeResponse(trigger, flowContext);
721
- return flowContext;
722
- }
723
- };
724
- var client_service_default = FlowClient;
725
-
726
- // client/client.service.spec.ts
727
- describe("FlowClient", () => {
728
- let client;
729
- const validUUID = "123e4567-e89b-12d3-a456-426614174000";
730
- const validFlowId = "4f3d2a1b6c8e9f0d7a2b3c4d";
731
- const validOptions = {
732
- baseUrl: "https://api.example.com",
733
- organizationId: validUUID,
734
- flowId: validFlowId,
735
- lang: "en"
736
- };
737
- const validStepOptions = {
738
- state: { someKey: "someValue" }
739
- };
740
- const validResponse = {
741
- status: "ok",
742
- step: {
743
- id: "step-id"
744
- },
745
- flow: {
746
- id: validFlowId,
747
- updatedAt: "2021-01-01T00:00:00Z",
748
- organizationId: validUUID,
749
- stages: []
750
- }
751
- };
752
- beforeEach(() => {
753
- vi.clearAllMocks();
754
- global.fetch = vi.fn();
755
- client = new client_service_default(validOptions);
756
- });
757
- describe("Constructor", () => {
758
- it("should create instance with correct configuration", () => {
759
- const client2 = new client_service_default(validOptions);
760
- expect(client2["baseURL"]).toBe(validOptions.baseUrl);
761
- expect(client2["headers"].get("Content-Type")).toBe("application/json");
762
- expect(client2["headers"].get("X-Onlive-Organization-Id")).toBe(validOptions.organizationId);
763
- });
764
- it("should throw error if baseUrl is invalid", () => {
765
- const invalidOptions = {
766
- baseUrl: "invalid-url",
767
- organizationId: validUUID,
768
- flowId: validFlowId,
769
- lang: "en"
770
- };
771
- expect(() => new client_service_default(invalidOptions)).toThrow(ZodError);
772
- });
773
- it("should throw error if organizationId is missing", () => {
774
- const invalidOptions = {
775
- baseUrl: "https://api.example.com",
776
- flowId: validFlowId,
777
- lang: "en"
778
- };
779
- expect(() => new client_service_default(invalidOptions)).toThrow(ZodError);
780
- });
781
- it("should throw error if organizationId is not a valid UUID", () => {
782
- const invalidOptions = {
783
- baseUrl: "https://api.example.com",
784
- organizationId: "invalid-uuid",
785
- flowId: validFlowId,
786
- lang: "en"
787
- };
788
- expect(() => new client_service_default(invalidOptions)).toThrow(ZodError);
789
- });
790
- it("should throw error if lang is missing", () => {
791
- const invalidOptions = {
792
- baseUrl: "https://api.example.com",
793
- organizationId: validUUID,
794
- flowId: validFlowId
795
- };
796
- expect(() => new client_service_default(invalidOptions)).toThrow(ZodError);
797
- });
798
- it("should throw error if lang length is not 2", () => {
799
- const invalidOptions = {
800
- baseUrl: "https://api.example.com",
801
- organizationId: validUUID,
802
- flowId: validFlowId,
803
- lang: "english"
804
- };
805
- expect(() => new client_service_default(invalidOptions)).toThrow(ZodError);
806
- });
807
- });
808
- describe("firstStep", () => {
809
- it("should make POST request to /flow/:flowId/first-step", async () => {
810
- const mockResponse = validResponse;
811
- global.fetch = vi.fn().mockResolvedValue({
812
- ok: true,
813
- json: () => Promise.resolve(mockResponse)
814
- });
815
- const result = await client.firstStep(validStepOptions);
816
- expect(global.fetch).toHaveBeenCalledWith(
817
- `${validOptions.baseUrl}/flow/${validOptions.flowId}/first-step`,
818
- expect.objectContaining({
819
- method: "POST",
820
- headers: expect.any(Headers),
821
- body: JSON.stringify(validStepOptions)
822
- })
823
- );
824
- expect(result).toEqual(mockResponse);
825
- });
826
- it("should throw error if options are invalid", async () => {
827
- const invalidOptions = { state: "invalid-state" };
828
- await expect(client.firstStep(invalidOptions)).rejects.toThrow(Error);
829
- });
830
- it("should handle HTTP error", async () => {
831
- global.fetch = vi.fn().mockResolvedValue({
832
- ok: false,
833
- status: 500
834
- });
835
- await expect(client.firstStep(validStepOptions)).rejects.toThrow("HTTP error! status: 500");
836
- });
837
- });
838
- describe("getStep", () => {
839
- const stepId = "step-123";
840
- it("should make POST request to /flow/:flowId/steps/:stepId", async () => {
841
- const mockResponse = validResponse;
842
- global.fetch = vi.fn().mockResolvedValue({
843
- ok: true,
844
- json: () => Promise.resolve(mockResponse)
845
- });
846
- const result = await client.getStep(stepId, validStepOptions);
847
- expect(global.fetch).toHaveBeenCalledWith(
848
- `${validOptions.baseUrl}/flow/${validOptions.flowId}/steps/${stepId}`,
849
- expect.objectContaining({
850
- method: "POST",
851
- headers: expect.any(Headers),
852
- body: JSON.stringify(validStepOptions)
853
- })
854
- );
855
- expect(result).toEqual(mockResponse);
856
- });
857
- it("should throw error if options are invalid", async () => {
858
- const invalidOptions = { state: "invalid-state" };
859
- await expect(client.getStep(stepId, invalidOptions)).rejects.toThrow(Error);
860
- });
861
- it("should handle HTTP error", async () => {
862
- global.fetch = vi.fn().mockResolvedValue({
863
- ok: false,
864
- status: 500
865
- });
866
- await expect(client.getStep(stepId, validStepOptions)).rejects.toThrow(
867
- "HTTP error! status: 500"
868
- );
869
- });
870
- });
871
- describe("nextStep", () => {
872
- const trigger = { currentStepId: "step-123", actionId: "action-123" };
873
- it("should make POST request to /flow/:flowId/steps/:currentStepId/action/:actionId", async () => {
874
- const mockResponse = validResponse;
875
- global.fetch = vi.fn().mockResolvedValue({
876
- ok: true,
877
- json: () => Promise.resolve(mockResponse)
878
- });
879
- const result = await client.nextStep(trigger, validStepOptions);
880
- expect(global.fetch).toHaveBeenCalledWith(
881
- `${validOptions.baseUrl}/flow/${validOptions.flowId}/steps/${trigger.currentStepId}/action/${trigger.actionId}`,
882
- expect.objectContaining({
883
- method: "POST",
884
- headers: expect.any(Headers),
885
- body: JSON.stringify(validStepOptions)
886
- })
887
- );
888
- expect(result).toEqual(mockResponse);
889
- });
890
- it("should validate trigger", async () => {
891
- const invalidTrigger = {};
892
- await expect(client.nextStep(invalidTrigger, validStepOptions)).rejects.toThrow(ZodError);
893
- });
894
- it("should throw error if options are invalid", async () => {
895
- const invalidOptions = { state: "invalid-state" };
896
- await expect(client.nextStep(trigger, invalidOptions)).rejects.toThrow(ZodError);
897
- });
898
- it("should handle HTTP error", async () => {
899
- global.fetch = vi.fn().mockResolvedValue({
900
- ok: false,
901
- status: 500
902
- });
903
- await expect(client.nextStep(trigger, validStepOptions)).rejects.toThrow(
904
- "HTTP error! status: 500"
905
- );
906
- });
907
- });
908
- });
1
+ /*! @onlive.ai/flow-client v0.1.44 | © 2025 Onlive.ai */
2
+ var R=Object.defineProperty;var C=(r,o,e)=>o in r?R(r,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[o]=e;var m=(r,o,e)=>C(r,typeof o!="symbol"?o+"":o,e);import{beforeEach as tt,describe as h,expect as a,it as l,vi as f}from"vitest";import{ZodError as b}from"zod";import{merge as Q}from"@onlive.ai/common-121/utils/merge.js";import{Session as w,Tracker as D}from"@onlive.ai/tracker";import{merge as F}from"@onlive.ai/common-121/utils/merge.js";import{browserPreferences as U}from"@onlive.ai/common-121/utils/browser-preferences.js";import{z as c}from"zod";var y="flow_form",E="onlive-analytics-event",v=c.object({enabled:c.boolean().default(!1).optional(),data:c.custom().optional(),removeExtraneousValues:c.boolean().default(!0).optional(),allowBotTraffic:c.boolean().default(!1).optional(),adapters:c.array(c.string()).default([]).optional(),apiUrl:c.string().url().optional(),emitters:c.object({windowEvent:c.boolean().optional(),dataLayer:c.boolean().optional(),windowPostMessage:c.boolean().optional()}).optional()});var k=class{constructor(o,e,i,s){m(this,"options");m(this,"tracker");m(this,"eventListeners",[]);this.options=v.parse(i),this.tracker=new D({apiUrl:this.options.apiUrl,removeExtraneousValues:this.options.removeExtraneousValues,allowBotTraffic:this.options.allowBotTraffic,adapters:this.options.adapters,dryRun:s}),this.tracker.setBase(F({},{organization_id:o,page_url:window.location.href,page_referrer:document.referrer,origin_medium:"web",guest_id:w.id,interaction_id:w.interactionId,extra:{flow_id:e}},this.options.data)),window.addEventListener(E,({detail:d})=>this.emit(d.event,d.data))}getTracker(){return this.tracker}preferences(){return{...U(),interactionId:w.interactionId,guestId:w.id}}analyzeRequest(o,e){"currentStepId"in o&&(o.actionId&&this.tracker.send("element_click",{element_label:o.actionId,element_type:"button",form_name:Object.keys(e.fields||{}).length?y:void 0,step_name:o.currentStepId}),e.fields&&this.tracker.send("form_submit",{form_name:y,form_data:e.fields,step_name:o.currentStepId}))}analyzeResponse(o,e){"currentStepId"in o&&(e.step.result?.pipelines&&e.step.result.pipelines.forEach(i=>{this.tracker.send("task_success",{task_name:i.name,task_data:i.data,step_name:e.step.id})}),e.step.error&&this.tracker.send("form_error",{form_name:y,form_error:e.step.error.code,step_name:e.step.id})),this.tracker.send("impression",{impression_type:"step",form_name:void 0,step_name:e.step.id,step_initial:!("currentStepId"in o)||void 0,step_final:e.step.isFinal}),this.tracker.setBase({form_name:y,step_name:e.step.id,step_initial:!("currentStepId"in o)||void 0,step_final:e.step.isFinal,...e.step.result?.tracking})}send(o,e){this.tracker.send(o,e)}setData(o){this.tracker.setBase(o)}onEvent(o){this.eventListeners.push(o)}emit(o,e){this.eventListeners.forEach(i=>i({event:o,data:e}))}},j=k;import{GetAvailabilityFilters as V,GetAvailabilityOptions as G}from"@onlive.ai/calendar";import{z as t}from"zod";var N={tracking:{removeExtraneousValues:!0,apiUrl:"https://srvless.onlive.site/tracking",data:{widget_type:"OnliveAppFlow"}}},A=t.string().nonempty(),L=t.object({baseUrl:t.string().url().nonempty(),flowId:t.string().length(24).nonempty(),organizationId:t.string().uuid().nonempty(),lang:t.string().length(2).nonempty(),tracking:v.optional(),devMode:t.boolean().default(!1).optional()}),x=t.object({state:t.record(t.string(),t.any()).optional(),fields:t.record(t.string(),t.any()).optional()}),P=t.object({currentStepId:t.string().nonempty(),actionId:t.string().nonempty()}),z=t.enum(["text","boolean","number","email","phone","mobile_phone","date","time","datetime","password","url","color","object","void","location","availability"]),$=t.object({name:t.string(),value:t.string().optional(),icon:t.string().optional(),type:t.enum(["url","email","phone"]).optional()}),M=t.object({lat:t.number().min(-90).max(90),lng:t.number().min(-180).max(180),meta:t.record(t.string(),t.any()).optional(),properties:t.record(t.string(),$).optional()}),q=t.object({datetime:t.string().datetime(),meta:t.record(t.string(),t.any()).optional()}),T=t.union([t.string(),t.number(),t.boolean(),M,q]),O=t.object({content:t.object({icon:t.string().optional(),url:t.string().url().optional(),width:t.string().optional(),height:t.string().optional(),scale:t.number().optional()}).optional(),background:t.string().optional(),glyph:t.object({color:t.string().optional(),url:t.string().url().optional(),icon:t.string().optional()}).optional(),borderColor:t.string().optional(),scale:t.number().optional()}),I=t.custom(r=>/^\d{4}-\d{2}-\d{2}$/.test(r),{message:"Date must be in 'YYYY-MM-DD' format"}),g=t.object({text:t.string().optional(),icon:t.string().optional()}),B=t.object({name:t.string().nonempty(),label:t.string().optional(),value:t.union([T,t.array(T)]).optional(),type:z,component:t.enum(["input","textarea","select","radio","checkbox","switch","rating","carousel","button","label","map","calendar"]).optional(),disabled:t.boolean().optional(),readonly:t.boolean().optional(),multiple:t.boolean().optional(),placeholder:t.string().optional(),options:t.array(t.object({label:t.string().nonempty(),value:T.optional(),image:t.string().url().optional(),description:t.string().optional(),disabled:t.boolean().optional(),attributes:t.record(t.string(),t.any()).optional()})).optional(),required:t.boolean().optional(),configuration:t.object({input:t.object({min:t.number().optional(),max:t.number().optional(),step:t.number().optional(),pattern:t.string().refine(r=>{try{return new RegExp(r),!0}catch{return!1}},"Invalid regex pattern").optional(),minLength:t.number().optional(),maxLength:t.number().optional(),exactLength:t.number().optional(),prefix:t.object({default:g.optional(),success:g.optional(),error:g.optional()}).optional(),suffix:t.object({default:g.optional(),success:g.optional(),error:g.optional()}).optional(),clearable:t.boolean().optional(),floatingLabel:t.boolean().optional()}).optional(),textarea:t.object({rows:t.number().optional()}).optional(),checkbox:t.object({layout:t.enum(["horizontal","vertical"])}).optional(),rating:t.object({icons:t.array(t.string()).optional(),color:t.string().optional(),precision:t.number().optional()}).optional(),map:t.object({apiKey:t.string().optional(),region:t.string().length(2).optional(),center:t.object({lat:t.number().min(-90).max(90),lng:t.number().min(-180).max(180)}).optional(),showMap:t.enum(["always","on-search"]).optional(),zoom:t.object({initial:t.number().optional(),focus:t.number().optional(),max:t.number().optional(),min:t.number().optional()}).optional(),controls:t.object({fullscreen:t.boolean().optional(),mapType:t.boolean().optional(),zoom:t.boolean().optional(),rotate:t.boolean().optional(),scale:t.boolean().optional(),streetView:t.boolean().optional()}).optional(),initialLocations:t.number().optional(),maxLocations:t.number().optional(),distanceUnit:t.enum(["km","mi"]).optional(),distanceFormat:t.enum(["short","long"]).optional(),options:t.object({show:t.enum(["always","on-search","never"]).optional(),component:t.enum(["list-button","list-radio","carousel"]).optional(),searchLabel:t.string().optional(),detailsLabel:t.string().optional()}).optional(),search:t.object({value:t.string().optional(),button:t.object({label:t.string().optional(),position:t.enum(["inside","outside"]).optional()}).optional(),placeholder:t.string().optional(),noResultsText:t.string().optional(),autocomplete:t.boolean().optional(),clearable:t.boolean().optional(),mode:t.enum(["address","postcode"]).default("postcode").optional(),locationButton:t.object({icon:t.string().optional(),position:t.enum(["left","right"]).optional()}).optional(),prefix:t.object({default:g.optional()}).optional(),suffix:t.object({default:g.optional()}).optional(),mappedResults:t.object({mapping:t.record(t.string(),t.array(t.object({key:t.string(),value:t.string()})))}).optional()}).optional(),distanceRange:t.object({initial:t.number().optional(),min:t.number().optional(),max:t.number().optional(),step:t.number().optional()}).optional(),mapRegion:t.object({strokeColor:t.string().optional(),fillColor:t.string().optional(),fillOpacity:t.number().optional()}).optional(),locationPin:O.optional(),markerPin:t.object({default:O.optional(),hover:O.optional(),selected:O.optional()}).optional(),infoWindow:t.object({button:t.object({label:t.string(),action:t.string()}).optional()}).optional()}).optional(),calendar:t.object({current:t.object({month:t.number().min(0).max(11).optional(),year:t.number().optional()}).optional(),range:t.object({min:I.optional(),max:I.optional(),enabled:t.array(I).optional(),disabled:t.array(I).optional()}).optional(),time:t.object({label:t.string().optional(),format:t.enum(["12h","24h"]).optional(),component:t.enum(["carousel","list"]).optional()}).optional(),api:t.object({url:t.string().url().nonempty(),organizationId:t.string().nonempty(),availability:t.object({filters:V,options:G.optional()}).optional()}).optional()}).optional()}).optional(),dependsOn:t.array(t.object({fieldName:t.string().nonempty(),value:T.optional()})).optional(),dependentBehavior:t.enum(["hidden","disabled"]).optional(),customError:t.object({required:t.string().optional(),invalid:t.string().optional(),minLength:t.string().optional(),maxLength:t.string().optional(),minValue:t.string().optional(),maxValue:t.string().optional(),mismatch:t.string().optional()}).optional()}),H=t.object({src:t.string().url(),preload:t.boolean().optional(),name:t.string().nonempty(),function:t.string().nonempty(),params:t.record(t.string(),t.any()).optional()}),W=t.object({name:t.enum(["organization_call","close_panel"]),params:t.record(t.string(),t.any()).optional()}),Y=t.object({id:t.string().nonempty(),type:t.enum(["submit","navigate","link","back","dispatcher","script"]),label:t.string().nonempty(),variant:t.enum(["primary","secondary","success","danger","warning","info"]),url:t.string().url().optional(),scripts:H.array().optional(),events:W.array().optional()}),K=t.enum(["INVALID_DATA","INVALID_ACTION","STEP_NOT_FOUND","UNKNOWN_ERROR","APPOINTMENT_INVALID_DATA","APPOINTMENT_BUSY_SLOT","APPOINTMENT_OUT_OF_DATE","APPOINTMENT_UNKNOWN_ERROR","LEAD_INVALID_DATA","LEAD_UNKNOWN_ERROR","CONTENT_INVALID_DATA","CONTENT_UNKNOWN_ERROR","CONTACT_INVALID_DATA","CONTACT_UNKNOWN_ERROR","LOST_OPPORTUNITY_INVALID_DATA","LOST_OPPORTUNITY_UNKNOWN_ERROR"]),J=t.object({type:t.enum(["redirect"]),params:t.record(t.string(),t.any()).optional()}),Z=t.object({id:t.string().nonempty(),title:t.string().optional(),description:t.string().optional(),stageId:t.string().optional(),state:t.record(t.string(),t.any()).optional(),fields:t.array(B).optional(),actions:t.array(Y).optional(),result:t.object({postActions:t.array(J).optional(),pipelines:t.array(t.object({name:t.string(),data:t.object({})})).optional(),tracking:t.record(t.string(),t.any()).optional()}).optional(),error:t.object({code:K,message:t.string().optional(),fields:t.array(t.object({name:t.string(),type:z,value:t.any(),error:t.string()})).optional()}).optional(),isFinal:t.boolean().optional()}),X=t.object({id:t.string().length(24).nonempty(),organizationId:t.string().uuid().nonempty(),updatedAt:t.string().datetime().nonempty(),stages:t.array(t.object({id:t.string().nonempty(),name:t.string().nonempty()}))}),yt=t.object({status:t.enum(["ok","error"]),step:Z,flow:X}),ht=t.enum(["track"]);var _=class{constructor(o){m(this,"baseURL");m(this,"headers");m(this,"flowId");m(this,"tracking");let e=Q({},N,L.parse(o));this.flowId=e.flowId,this.baseURL=e.baseUrl,this.headers=new Headers({"Content-Type":"application/json","X-Onlive-Organization-Id":e.organizationId,"X-Lang":e.lang}),e.tracking?.enabled&&(this.tracking=new j(e.organizationId,e.flowId,e.tracking,!!e.devMode))}async request(o,e={}){let i=await fetch(`${this.baseURL}/${o}`,{...e,headers:this.headers});if(!i?.ok)throw new Error(`HTTP error! status: ${i?.status||"unknown"}`);return i.json()}async firstStep(o={}){this.tracking?.analyzeRequest({},o);let e=this.tracking?.preferences(),i=await this.request(`flow/${this.flowId}/first-step`,{method:"POST",body:JSON.stringify(x.parse({...o,state:{preferences:e,...o.state}}))});return this.tracking?.analyzeResponse({},i),i}async getStep(o,e={}){this.tracking?.analyzeRequest({stepId:o},e);let i=this.tracking?.preferences(),s=await this.request(`flow/${this.flowId}/steps/${A.parse(o)}`,{method:"POST",body:JSON.stringify(x.parse({...e,state:{preferences:i,...e.state}}))});return this.tracking?.analyzeResponse({stepId:o},s),s}async nextStep(o,e={}){this.tracking?.analyzeRequest(o,e);let{currentStepId:i,actionId:s}=P.parse(o),d=await this.request(`flow/${this.flowId}/steps/${i}/action/${s}`,{method:"POST",body:JSON.stringify(x.parse(e))});return this.tracking?.analyzeResponse(o,d),d}},u=_;h("FlowClient",()=>{let r,o="123e4567-e89b-12d3-a456-426614174000",e="4f3d2a1b6c8e9f0d7a2b3c4d",i={baseUrl:"https://api.example.com",organizationId:o,flowId:e,lang:"en"},s={state:{someKey:"someValue"}},d={status:"ok",step:{id:"step-id"},flow:{id:e,updatedAt:"2021-01-01T00:00:00Z",organizationId:o,stages:[]}};tt(()=>{f.clearAllMocks(),global.fetch=f.fn(),r=new u(i)}),h("Constructor",()=>{l("should create instance with correct configuration",()=>{let n=new u(i);a(n.baseURL).toBe(i.baseUrl),a(n.headers.get("Content-Type")).toBe("application/json"),a(n.headers.get("X-Onlive-Organization-Id")).toBe(i.organizationId)}),l("should throw error if baseUrl is invalid",()=>{let n={baseUrl:"invalid-url",organizationId:o,flowId:e,lang:"en"};a(()=>new u(n)).toThrow(b)}),l("should throw error if organizationId is missing",()=>{let n={baseUrl:"https://api.example.com",flowId:e,lang:"en"};a(()=>new u(n)).toThrow(b)}),l("should throw error if organizationId is not a valid UUID",()=>{let n={baseUrl:"https://api.example.com",organizationId:"invalid-uuid",flowId:e,lang:"en"};a(()=>new u(n)).toThrow(b)}),l("should throw error if lang is missing",()=>{let n={baseUrl:"https://api.example.com",organizationId:o,flowId:e};a(()=>new u(n)).toThrow(b)}),l("should throw error if lang length is not 2",()=>{let n={baseUrl:"https://api.example.com",organizationId:o,flowId:e,lang:"english"};a(()=>new u(n)).toThrow(b)})}),h("firstStep",()=>{l("should make POST request to /flow/:flowId/first-step",async()=>{let n=d;global.fetch=f.fn().mockResolvedValue({ok:!0,json:()=>Promise.resolve(n)});let p=await r.firstStep(s);a(global.fetch).toHaveBeenCalledWith(`${i.baseUrl}/flow/${i.flowId}/first-step`,a.objectContaining({method:"POST",headers:a.any(Headers),body:JSON.stringify(s)})),a(p).toEqual(n)}),l("should throw error if options are invalid",async()=>{let n={state:"invalid-state"};await a(r.firstStep(n)).rejects.toThrow(Error)}),l("should handle HTTP error",async()=>{global.fetch=f.fn().mockResolvedValue({ok:!1,status:500}),await a(r.firstStep(s)).rejects.toThrow("HTTP error! status: 500")})}),h("getStep",()=>{let n="step-123";l("should make POST request to /flow/:flowId/steps/:stepId",async()=>{let p=d;global.fetch=f.fn().mockResolvedValue({ok:!0,json:()=>Promise.resolve(p)});let S=await r.getStep(n,s);a(global.fetch).toHaveBeenCalledWith(`${i.baseUrl}/flow/${i.flowId}/steps/${n}`,a.objectContaining({method:"POST",headers:a.any(Headers),body:JSON.stringify(s)})),a(S).toEqual(p)}),l("should throw error if options are invalid",async()=>{let p={state:"invalid-state"};await a(r.getStep(n,p)).rejects.toThrow(Error)}),l("should handle HTTP error",async()=>{global.fetch=f.fn().mockResolvedValue({ok:!1,status:500}),await a(r.getStep(n,s)).rejects.toThrow("HTTP error! status: 500")})}),h("nextStep",()=>{let n={currentStepId:"step-123",actionId:"action-123"};l("should make POST request to /flow/:flowId/steps/:currentStepId/action/:actionId",async()=>{let p=d;global.fetch=f.fn().mockResolvedValue({ok:!0,json:()=>Promise.resolve(p)});let S=await r.nextStep(n,s);a(global.fetch).toHaveBeenCalledWith(`${i.baseUrl}/flow/${i.flowId}/steps/${n.currentStepId}/action/${n.actionId}`,a.objectContaining({method:"POST",headers:a.any(Headers),body:JSON.stringify(s)})),a(S).toEqual(p)}),l("should validate trigger",async()=>{let p={};await a(r.nextStep(p,s)).rejects.toThrow(b)}),l("should throw error if options are invalid",async()=>{let p={state:"invalid-state"};await a(r.nextStep(n,p)).rejects.toThrow(b)}),l("should handle HTTP error",async()=>{global.fetch=f.fn().mockResolvedValue({ok:!1,status:500}),await a(r.nextStep(n,s)).rejects.toThrow("HTTP error! status: 500")})})});