@onlive.ai/flow-client 0.1.37 → 0.1.40

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