@onlive.ai/flow-client
v0.1.228
Published
> TypeScript client for interacting with multi-step Onlive flows. Provides a type-safe, promise-based API with runtime validation and built-in event tracking.
Readme
@onlive.ai/flow-client
TypeScript client for interacting with multi-step Onlive flows. Provides a type-safe, promise-based API with runtime validation and built-in event tracking.
Overview
@onlive.ai/flow-client is the headless data layer behind Onlive interactive flows. It handles API communication, step navigation, field submission, and analytics tracking — without any rendering logic.
Use this package directly when you want to build a fully custom flow UI. If you need ready-made web components, use @onlive.ai/flow, which consumes this client internally.
Installation
Prerequisites: Node.js 18+
# pnpm (recommended)
pnpm add @onlive.ai/flow-client
# npm
npm install @onlive.ai/flow-client
# yarn
yarn add @onlive.ai/flow-clientQuick Start
import { FlowClient } from "@onlive.ai/flow-client";
const client = new FlowClient({
baseUrl: "https://flow-api.onlive.site",
flowId: "0123456789abcdef01234567",
organizationId: "550e8400-e29b-41d4-a716-446655440000",
lang: "en",
});
client.on("track", (eventType, eventData) => {
console.log("Track event:", eventType, eventData);
});
const context = await client.firstStep();
console.log(context.step.title);Package Structure
packages/flow-client/
├── client/
│ ├── client.service.ts # FlowClient class implementation
│ ├── client.types.ts # Zod schemas and inferred TypeScript types
│ └── client.service.spec.ts # Unit tests
├── tracking/
│ ├── tracking.service.ts # Tracking service implementation
│ └── tracking.types.ts # Tracking-related types and schemas
├── flow.types.ts # Flow-specific type definitions
├── index.ts # Package entry point and exports
└── schema-generator.ts # JSON schema generation utilitiesExports
// Client
export { FlowClient } from "@onlive.ai/flow-client";
// Types
export type { ClientOptions, GetStepOptions, GetStepTrigger } from "@onlive.ai/flow-client";
export type { FlowContext, Step, Flow, Action } from "@onlive.ai/flow-client";
export type { TrackingOptions } from "@onlive.ai/flow-client";
export type { EventData, EventName } from "@onlive.ai/flow-client";Build Formats
| Format | File | Use Case |
|------------|---------------|---------------------------------------------|
| ESM | index.js | Modern bundlers (Vite, Webpack, Rollup) |
| CommonJS | index.cjs | Node.js environments |
| TypeScript | index.d.ts | TypeScript type definitions |
API Reference
FlowClient
The main class. Instantiate it once per flow session and call its methods to navigate steps.
All constructor options are validated at runtime using Zod.
Constructor
new FlowClient(options: ClientOptions)ClientOptions
| Property | Type | Required | Default | Description |
|---------------|-------------------|----------|---------|-------------|
| baseUrl | string | Yes | — | Base URL of the Flow API. Must be a valid URL. |
| flowId | string | Yes | — | Flow identifier. Must be exactly 24 characters. |
| organizationId | string | Yes | — | Organization UUID. |
| lang | string | Yes | — | BCP 47 language code, 2 characters (e.g. "en", "es"). |
| tracking | TrackingOptions | No | — | Analytics tracking configuration. See TrackingOptions. |
| devMode | boolean | No | false | Enables development mode logging. |
import { FlowClient, type ClientOptions } from "@onlive.ai/flow-client";
const client = new FlowClient({
baseUrl: "https://flow-api.onlive.site",
flowId: "0123456789abcdef01234567",
organizationId: "550e8400-e29b-41d4-a716-446655440000",
lang: "en",
tracking: {
enabled: true,
apiUrl: "https://srvless.onlive.site/tracking",
emitters: {
windowEvent: true,
dataLayer: false,
},
},
});Methods
firstStep(options?: GetStepOptions): Promise<FlowContext>
Initiates the flow and returns the first step.
Sends a POST request to flow/{flowId}/first-step.
const context = await client.firstStep({
state: { source: "homepage" },
fields: { prefill_email: "[email protected]" },
});getStep(stepId: string, options?: GetStepOptions): Promise<FlowContext>
Retrieves a specific step by its identifier.
Sends a POST request to flow/{flowId}/steps/{stepId}.
const context = await client.getStep("64abc123def456789012abc3", {
state: { retryCount: 1 },
});nextStep(trigger: GetStepTrigger, options?: GetStepOptions): Promise<FlowContext>
Advances the flow to the next step based on the user's action.
Sends a POST request to flow/{flowId}/steps/{currentStepId}/action/{actionId}.
const context = await client.nextStep(
{
currentStepId: "64abc123def456789012abc3",
actionId: "submit",
},
{
fields: { email: "[email protected]", phone: "+34600000000" },
},
);on(type: EventType, listener: EventListener): void
Registers a listener for client events. Currently supports the "track" event type, fired whenever the client emits an analytics event.
client.on("track", (eventType, eventData) => {
// eventType: EventName
// eventData: EventData
analytics.push({ event: eventType, ...eventData });
});Input Types
GetStepOptions
Optional payload accepted by firstStep(), getStep(), and nextStep().
| Property | Type | Description |
|----------|------------------------|-------------|
| state | Record<string, any> | Arbitrary state data to pass to the flow engine. |
| fields | Record<string, any> | Field values to submit or pre-fill in the step. |
GetStepTrigger
Required first argument for nextStep().
| Property | Type | Description |
|-----------------|----------|-------------|
| currentStepId | string | Identifier of the currently active step. Must be non-empty. |
| actionId | string | Identifier of the action the user triggered. Must be non-empty. |
Response Types
FlowContext
Returned by all step methods.
| Property | Type | Description |
|----------|--------------------|-------------|
| status | "ok" \| "error" | Result status of the flow operation. |
| step | Step | The current step to render. |
| flow | Flow | Flow configuration and stage metadata. |
Step
| Property | Type | Description |
|----------------------|-------------------------------------------------------------------|-------------|
| id | string | Unique step identifier. |
| number | number | Optional sequential position in the flow. |
| title | string | Optional display title. |
| description | string | Optional contextual description. |
| stageId | string | Optional identifier of the associated flow stage. |
| state | Record<string, any> | Optional state data for the step. |
| fields | Field[] | Optional array of form fields to render. |
| actions | Action[] | Optional array of available actions (buttons). |
| result.postActions | PostAction[] | Optional post-actions to execute after step completion (e.g. redirect). |
| result.tracking | StepResultTracking \| StepResultTracking[] | Optional tracking payload(s) for this step result. |
| error.code | ErrorCode | Error code when status is "error". |
| error.message | string | Optional human-readable error message. |
| error.icon | string | Optional icon name to display with the error. |
| error.position | "top" \| "bottom" | Optional position of the error message. |
| error.fields | Array<{ name: string; type: string; value: any; error: string }> | Optional per-field validation errors. |
| isFinal | boolean | When true, this is the last step in the flow. |
Flow
| Property | Type | Description |
|------------------|----------------------------------------|-------------|
| id | string | Flow identifier. Exactly 24 characters. |
| organizationId | string | UUID of the owning organization. |
| updatedAt | string | ISO 8601 datetime of the last update. |
| stages | Array<{ id: string; name: string }> | Ordered array of flow stages. |
Action
Actions describe buttons or interactive controls within a step.
| Property | Type | Required | Description |
|-------------------|-----------------------------------------------------------------------------------|----------|-------------|
| id | string | Yes | Unique action identifier. |
| type | "submit" \| "navigate" \| "link" \| "back" \| "dispatcher" \| "script" | Yes | Determines the behavior when triggered. |
| label | string | Yes | Display text for the button. |
| variant | "primary" \| "secondary" \| "success" \| "danger" \| "warning" \| "info" | Yes | Visual style variant. |
| position | "top" \| "bottom" | No | Position of the button relative to step content. |
| url | string | No | Target URL for link type actions. Must be a valid URL. |
| target | "_self" \| "_blank" \| "_parent" \| "_top" | No | Link target attribute. |
| loadingBehavior | "none" \| "spinner" \| "disabled" | No | How the button behaves while loading. |
| prefix | AffixSlot | No | Icon or text to display before the label. |
| suffix | AffixSlot | No | Icon or text to display after the label. |
| scripts | ActionScript[] | No | Scripts to execute when the action is triggered. |
| events | ActionEvent[] | No | Custom events to emit when the action is triggered. |
ActionScript
| Property | Type | Required | Description |
|------------|----------------------------|----------|-------------|
| src | string | Yes | URL of the script to load. Must be a valid URL. |
| name | string | Yes | Identifier for the script. |
| function | string | Yes | Name of the function to invoke from the script. |
| preload | boolean | No | Whether to preload the script before execution. |
| params | Array<Record<string, any>> | No | Parameter objects passed to the script function. |
ActionEvent
| Property | Type | Required | Description |
|----------|----------------------------------------------------------------------------------------------------------------|----------|-------------|
| name | "organization_call" \| "close_panel" \| "retry_first_step" \| "retry_next_step" \| "organization_chat" | Yes | Event name to dispatch. |
| params | Record<string, any> | No | Additional parameters for the event. |
AffixSlot
| Property | Type | Description |
|----------|----------|-------------|
| text | string | Text content to display. |
| icon | string | Icon name to display. |
Error Handling
When status is "error", inspect step.error.code to identify the failure reason.
ErrorCode
| Code | Description |
|-----------------------------------|-------------|
| INVALID_DATA | The submitted data failed validation. |
| INVALID_ACTION | The requested action does not exist or is not valid for the current step. |
| STEP_NOT_FOUND | The requested step does not exist. |
| UNKNOWN_ERROR | An unexpected error occurred. |
| APPOINTMENT_INVALID_DATA | Calendar appointment data is invalid. |
| APPOINTMENT_BUSY_SLOT | The selected appointment slot is already taken. |
| APPOINTMENT_OUT_OF_DATE | The selected appointment slot is in the past or no longer available. |
| APPOINTMENT_UNKNOWN_ERROR | An unexpected error occurred during appointment processing. |
| LEAD_INVALID_DATA | Lead data failed validation. |
| LEAD_UNKNOWN_ERROR | An unexpected error occurred during lead processing. |
| CONTENT_INVALID_DATA | Content data failed validation. |
| CONTENT_UNKNOWN_ERROR | An unexpected error occurred during content processing. |
| CONTACT_INVALID_DATA | Contact data failed validation. |
| CONTACT_UNKNOWN_ERROR | An unexpected error occurred during contact processing. |
| LOST_OPPORTUNITY_INVALID_DATA | Lost opportunity data failed validation. |
| LOST_OPPORTUNITY_UNKNOWN_ERROR | An unexpected error occurred during lost opportunity processing. |
const context = await client.nextStep({ currentStepId, actionId });
if (context.status === "error" && context.step.error) {
switch (context.step.error.code) {
case "APPOINTMENT_BUSY_SLOT":
// Prompt user to select a different time slot
break;
case "INVALID_DATA":
// Highlight invalid fields
context.step.error.fields?.forEach(({ name, error }) => {
console.warn(`Field "${name}": ${error}`);
});
break;
default:
console.error("Flow error:", context.step.error.message);
}
}TrackingOptions
| Property | Type | Default | Description |
|-----------------------------|--------------------|---------|-------------|
| enabled | boolean | false | Whether event tracking is active. |
| apiUrl | string | — | URL of the tracking API endpoint. |
| data | Partial<EventData> | — | Base data merged into every tracked event. |
| removeExtraneousValues | boolean | true | Strips unknown fields from event payloads before sending. |
| allowBotTraffic | boolean | false | Whether to track requests identified as bot traffic. |
| adapters | string[] | [] | Tracking adapter identifiers to activate. |
| emitters.windowEvent | boolean | — | Emits events as onlive-analytics-event window custom events. |
| emitters.dataLayer | boolean | — | Pushes events to window.dataLayer (Google Tag Manager). |
| emitters.windowPostMessage | boolean | — | Sends events via window.postMessage. |
Examples
Complete Flow Navigation
import { FlowClient } from "@onlive.ai/flow-client";
const client = new FlowClient({
baseUrl: "https://flow-api.onlive.site",
flowId: "0123456789abcdef01234567",
organizationId: "550e8400-e29b-41d4-a716-446655440000",
lang: "en",
tracking: { enabled: true, apiUrl: "https://srvless.onlive.site/tracking" },
});
client.on("track", (eventType, eventData) => {
console.log("Track:", eventType, eventData);
});
try {
const { step } = await client.firstStep();
if (step.isFinal) {
console.log("Flow completed on the first step.");
} else {
const next = await client.nextStep(
{ currentStepId: step.id, actionId: "submit" },
{ fields: { email: "[email protected]" } },
);
console.log("Next step:", next.step.title);
}
} catch (error) {
console.error("Unexpected error:", error);
}Resuming a Specific Step
const context = await client.getStep("64abc123def456789012abc3", {
state: { referrer: "email-campaign" },
});
console.log("Step fields:", context.step.fields?.map((f) => f.name));Dependencies
| Package | Purpose |
|------------------------------|---------|
| zod | Runtime schema validation for constructor options and API responses |
| @onlive.ai/tracker | Analytics event types and tracking infrastructure |
| @onlive.ai/common-121 | Shared utilities and types |
| @onlive.ai/calendar | Calendar utilities for appointment field handling |
Development
# Install dependencies
pnpm install
# Build the package (ESM + CJS)
pnpm run build:package
# Run unit tests
pnpm test
# Run tests with coverage
pnpm run test:coverage
# Remove generated build artifacts
pnpm run cleanRelated Packages
| Package | Description |
|---------|-------------|
| @onlive.ai/flow | Web components for rendering flows (uses this client internally) |
| @onlive.ai/calendar | Calendar components for date/appointment fields |
Documentation
License
Proprietary software — © Onlive.ai. All rights reserved.
For support, visit the Onlive documentation or contact the development team.
