npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

npm version TypeScript Lit License: Proprietary

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-client

Quick 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 utilities

Exports

// 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 clean

Related 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.