Skip to content

Latest commit

 

History

History

core

README.md

AsyncFlowState Logo

@asyncflowstate/core v3.0.0 Stable

Framework-agnostic async UI behavior orchestration engine.

Documentation License: MIT NPM Version


Installation

npm install @asyncflowstate/core
# or
pnpm add @asyncflowstate/core

Quick Start

import { Flow } from "@asyncflowstate/core";

// 1. Create a flow for any async action
const saveFlow = new Flow(async (data) => {
  const response = await fetch("/api/save", {
    method: "POST",
    body: JSON.stringify(data),
  });
  return response.json();
});

// 2. Subscribe to state changes
saveFlow.subscribe((state) => {
  console.log("Status:", state.status); // 'idle' | 'loading' | 'success' | 'error'
  console.log("Data:", state.data);
  console.log("Error:", state.error);
});

// 3. Execute the flow
await saveFlow.execute({ name: "John" });

Key Features

Concurrency Strategies

Control what happens when execute() is called while an action is already running.

  • keep (default): Ignore the new request.
  • restart: Abort the current request and start the new one.
const flow = new Flow(fetchData, { concurrency: "restart" });

Perception & UX Polish

Prevent UI flashes by ensuring loading states show for a appropriate amount of time.

  • delay: Wait before switching to loading status (prevents flicker for fast actions).
  • minDuration: Stay in loading state for at least this long once switched.
const flow = new Flow(saveData, {
  loading: {
    delay: 200, // Only show spinner if > 200ms
    minDuration: 500, // If shown, keep for at least 500ms
  },
});

Resilience (Retry)

Built-in retry logic with fixed, linear, or exponential backoff.

const flow = new Flow(flakeyAction, {
  retry: {
    maxAttempts: 3,
    delay: 1000,
    backoff: "exponential",
  },
});

Optimistic UI

Update the state immediately before the action completes.

const flow = new Flow(updateName, {
  optimisticResult: "New Name",
});

flow.execute();
console.log(flow.data); // "New Name" (instantly)

Progress Tracking

Manually report progress for long-running tasks.

const flow = new Flow(async () => {
  flow.setProgress(50); // halfway done
});

console.log(flow.progress); // 50

Polling

Automatically re-execute the action at a fixed interval.

const flow = new Flow(fetchPrice, {
  polling: {
    interval: 5000, // Every 5 seconds
    stopIf: (data) => data.isClosed, // Stop when condition met
    stopOnError: true,
  },
});

flow.execute(); // Starts execution and subsequent polls

Preconditions

Prevent execution based on custom logic.

const flow = new Flow(saveData, {
  precondition: () => isAuthenticated(),
  onBlocked: () => redirectToLogin(),
});

FlowSequence

Run multiple flows in order with shared state.

import { FlowSequence } from "@asyncflowstate/core";

const sequence = new FlowSequence([
  { name: "Auth", flow: loginFlow },
  { name: "Fetch", flow: dataFlow, mapInput: (auth) => auth.token },
]);

await sequence.execute();

FlowParallel

Execute multiple flows in parallel with aggregate state. Supports all, allSettled, and race strategies.

import { FlowParallel } from "@asyncflowstate/core";

const parallel = new FlowParallel([widget1Flow, widget2Flow], "all");
await parallel.execute();
console.log(parallel.state.progress); // Average progress of all flows

Streaming Support (LLM/AI)

Native support for AsyncIterable and ReadableStream. The flow status switches to 'streaming' until completion.

const flow = new Flow(async (prompt) => {
  const response = await ai.stream(prompt);
  return response.body; // ReadableStream
});

flow.subscribe((state) => {
  if (state.status === "streaming") {
    processChunk(state.data);
  }
});

Persistent Circuit Breaker

Prevents cascading failures by "tripping" the circuit after thresholds are met. State is persisted to localStorage.

const flow = new Flow(flakeyAPI, {
  circuitBreaker: {
    failureThreshold: 5,
    resetTimeout: 30000,
  },
  circuitBreakerKey: "user-api-circuit",
});

Declarative Chaining (Signals)

Use signals to chain flows without manual useEffect or complex orchestration.

const saveFlow = new Flow(saveUser);
const emailFlow = new Flow(sendEmail, {
  triggerOn: [saveFlow.signals.success],
});

Event System (Debugger Support)

Subscribe to global events for monitoring or logging.

const cleanup = Flow.onEvent((event) => {
  console.log(
    `${event.flowName} [${event.flowId}]: ${event.type}`,
    event.state,
  );
});

New in v3.0

  • Flow DNA: Self-healing async state that learns from environment patterns and user behavior.
  • Ambient Intelligence: Non-intrusive monitoring that predicts and optimizes background flows.
  • Flow Choreography: Declarative coordination of complex, multi-stage async workflows.
  • Speculative Execution: Run flows before users even click, based on high-confidence intent prediction.
  • Emotional UX: Adaptive UI transitions and skeleton states that respond to user sentiment and system load.
  • Flow Mesh: Cross-tab and cross-device orchestration with leader election and shared state.
  • Collaborative Flows: Sync async state in real-time across multiple users and browser sessions.
  • Temporal Replay: Time-travel through any async flow state with full state restoration.
  • Edge-First Flows: Optimized for Cloudflare Workers, Vercel Edge, and Deno with automatic failover.
  • Telemetry Dashboard: Real-time visualization of all flow health, latency, and throughput.

API Reference

Flow<TData, TError, TArgs>

Constructor

new Flow(action, options?)

Properties

  • status: 'idle' | 'loading' | 'streaming' | 'success' | 'error'
  • data: TData | null
  • error: TError | null
  • progress: number (0-100)
  • isLoading: boolean (Returns false if currently in loading.delay period)
  • state: The full state snapshot.

Methods

  • execute(...args: TArgs): Promise<TData | undefined>
  • cancel(): void
  • reset(): void
  • setProgress(value: number): void
  • subscribe(listener: (state) => void): () => void

License

MIT © AsyncFlowState Contributors