@asyncflowstate/core
v3.0.0
Published
Framework-agnostic core for AsyncFlowState. A tiny, powerful engine to orchestrate complex async UI behaviors, retries, and optimistic updates.
Maintainers
Readme
Installation
npm install @asyncflowstate/core
# or
pnpm add @asyncflowstate/coreQuick 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 toloadingstatus (prevents flicker for fast actions).minDuration: Stay inloadingstate 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); // 50Polling
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 pollsPreconditions
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 flowsStreaming 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 | nullerror:TError | nullprogress:number(0-100)isLoading:boolean(Returnsfalseif currently inloading.delayperiod)state: The full state snapshot.
Methods
execute(...args: TArgs): Promise<TData | undefined>cancel(): voidreset(): voidsetProgress(value: number): voidsubscribe(listener: (state) => void): () => void
