Skip to content

API Overview ​

SymbolPurposeExecution modeCommon gotcha
stream()Create cold streamLazyReturn one teardown function
pipe()Compose operatorsLazySource is first argument
of() / from()Convert known valuesSync / mixedfrom() promise cannot be aborted
fromEvent()Adapt event targetAsyncUnsubscribe removes listener
interval() / timer()Create timed valuesAsyncUse take() or unsubscribe for intervals
map() / filter() / scan()Transform valuesSyncCallback throws terminate stream
switchMap() / mergeMap() / concatMap()Flatten streamsMixedmergeMap() concurrency and queue are bounded; concatMap() queue is bounded
take() / takeUntil()Stop valuesMixedNotifier emission completes output
debounce() / timeout() / retry()Control time and failuresAsynctimeout() measures inactivity
merge() / concat() / combineLatest()Combine streamsMixedcombineLatest() waits for every source
toArray() / first() / last()Consume finite valuesAsyncBound toArray() with maxItems
toAsyncIterable()Use for awaitAsyncCapacity and overflow required
createChannel()Imperative multicast boundarySyncDispose to complete subscribers
fromStore()Bridge snapshot-based stateLazySnapshot and subscribe are both required
fromSubscribe()Bridge callback-delivered valuesLazyRegistration must return teardown

Package Entry Point ​

ImportPurpose
@vielzeug/fluxCore streams, operators, consumers, errors, types, and createChannel()
@vielzeug/flux/asynctoAsyncIterable() only

Core ​

stream() ​

ts
stream<T>(producer: Producer<T>): Stream<T>

Creates cold reusable work. Producer runs once for every subscription.

ParameterTypeDescription
producerProducer<T>Emits through sink and returns optional teardown

Returns: Stream<T>.

ts
import { stream } from '@vielzeug/flux';

const ticks = stream<number>((sink) => {
  const id = setInterval(() => sink.next(Date.now()), 1_000);
  return () => clearInterval(id);
});

pipe() ​

ts
pipe<Input, Operators>(source: Stream<Input>, ...operators: Operators): Stream<Output>

Applies operators left to right while inferring output value type.

ParameterTypeDescription
sourceStream<Input>Source stream
operatorsOperator[]Operators applied in order

Returns: transformed Stream<Output>.

ts
import { map, of, pipe } from '@vielzeug/flux';

const labels = pipe(of(1, 2), map((value) => `#${value}`));

Creation ​

of() ​

ts
of<T>(...values: T[]): Stream<T>

Emits every value synchronously, then completes.

ts
import { of } from '@vielzeug/flux';

of(1, 2, 3).subscribe(console.log);

from() ​

ts
from<T>(source: Iterable<T> | AsyncIterable<T> | Promise<T>): Stream<T>

Converts iterable, async iterable, or promise into a stream. Cancellation stops iterable consumption and calls return() when available.

ts
import { from } from '@vielzeug/flux';

from(Promise.resolve('ready')).subscribe({ error: console.error, next: console.log });

fromEvent() ​

ts
fromEvent<T = Event>(
  target: {
    addEventListener(type: string, listener: (event: T) => void): void;
    removeEventListener(type: string, listener: (event: T) => void): void;
  },
  type: string,
): Stream<T>

Emits target events until subscription ends.

ts
import { fromEvent } from '@vielzeug/flux';

fromEvent<MouseEvent>(document, 'click').subscribe(console.log);

interval() ​

ts
interval(every: number): Stream<number>

Emits incrementing values starting at zero.

ParameterTypeDescription
everynumberInterval duration from 0 through 2,147,483,647 milliseconds

timer() ​

ts
timer(options: TimerOptions): Stream<number>

Emits zero after delay; optionally continues at interval.

OptionTypeDescription
delaynumberInitial delay from 0 through 2,147,483,647 milliseconds
intervalnumberOptional repeat duration from 0 through 2,147,483,647 milliseconds

Transformation Operators ​

map() ​

ts
map<A, B>(project: (value: A) => B): Operator<A, B>

Maps every value. A thrown callback error terminates output.


filter() ​

ts
filter<T>(predicate: (value: T) => boolean): Operator<T, T>

Forwards values matching predicate.


scan() ​

ts
scan<T, A>(reducer: (state: A, value: T) => A, initial: A): Operator<T, A>

Emits accumulated state after every source value.


switchMap() ​

ts
switchMap<A, B>(project: (value: A) => Stream<B>): Operator<A, B>

Cancels previous inner stream when source emits.


mergeMap() ​

ts
mergeMap<A, B>(project: (value: A) => Stream<B>, options: FlattenOptions): Operator<A, B>

Runs inner streams with bounded concurrency and queue capacity. Exceeding capacity errors output with FluxCapacityError.

OptionTypeDescription
concurrencynumber | InfinityMaximum concurrently active inner subscriptions
capacitynumberPositive maximum queued source values (required when concurrency is finite)

concatMap() ​

ts
concatMap<A, B>(project: (value: A) => Stream<B>, options: { capacity: number }): Operator<A, B>

Runs inner streams in order (concurrency: 1). Exceeding capacity errors output with FluxCapacityError.

OptionTypeDescription
capacitynumberPositive maximum queued source values

Control Operators ​

take() ​

ts
take<T>(count: number): Operator<T, T>

Forwards count values, cancels upstream, then completes. Count must be non-negative integer.


takeUntil() ​

ts
takeUntil<T>(notifier: AbortSignal | Stream<unknown>): Operator<T, T>

Completes when notifier aborts or emits.


debounce() ​

ts
debounce<T>(duration: number): Operator<T, T>

Emits latest value after configured silence. Pending value flushes on source completion.

ParameterTypeDescription
durationnumberSilence duration from 0 through 2,147,483,647 milliseconds

timeout() ​

ts
timeout<T>(duration: number): Operator<T, T>

Errors with FluxTimeoutError when source is silent too long.

ParameterTypeDescription
durationnumberInactivity duration from 0 through 2,147,483,647 milliseconds

retry() ​

ts
retry<T>(options: RetryOptions): Operator<T, T>

Resubscribes after source errors until attempts are exhausted.

OptionTypeDescription
timesnumberNon-negative retry count
delaynumber | (attempt: number) => numberOptional delay/backoff returning 0 through 2,147,483,647 milliseconds

Combination ​

merge() ​

ts
merge<T>(...sources: Stream<T>[]): Stream<T>

Forwards values from all sources and completes after every source completes.


concat() ​

ts
concat<T>(...sources: Stream<T>[]): Stream<T>

Subscribes to each source only after previous source completes.


combineLatest() ​

ts
combineLatest<T extends readonly Stream<unknown>[]>(...sources: T): Stream<{ [K in keyof T]: T[K] extends Stream<infer V> ? V : never }>

Emits latest tuple after every source emits once. Completes without emission when a source completes before first value.

Value Consumers ​

toArray() ​

ts
toArray<T>(source: Stream<T>, options: ToArrayOptions): Promise<T[]>

Collects finite output. Rejects on source error, the supplied signal's abort reason, or maxItems overflow.

OptionTypeDescription
maxItemsnumberNon-negative maximum toArrayed values
signalAbortSignalOptional cancellation signal

first() ​

ts
first<T>(source: Stream<T>, options?: ValueOptions<T>): Promise<T>

Resolves first value and cancels source. Rejects on source error, the supplied signal's abort reason, or empty completion (FluxEmptyError); pass defaultValue to resolve instead.


last() ​

ts
last<T>(source: Stream<T>, options?: ValueOptions<T>): Promise<T>

Resolves last value on completion. Rejects on source error, the supplied signal's abort reason, or empty completion (FluxEmptyError); pass defaultValue to resolve instead.

Async Conversion ​

toAsyncIterable() ​

ts
toAsyncIterable<T>(source: Stream<T>, options: AsyncIterableOptions): AsyncIterable<T>

Converts a push stream to an async iterable with a bounded queue. External cancellation rejects pending iteration with signal.reason; explicit iterator return() completes normally. Overflow "error" rejects with FluxCapacityError; unsupported policies throw RangeError before subscription.

OptionTypeDescription
capacitynumberPositive queue capacity
overflowOverflowPolicyerror, drop-oldest, or drop-newest
signalAbortSignalOptional cancellation signal

Channels ​

createChannel() ​

ts
createChannel<T>(options?: ChannelOptions<T>): Channel<T>

Creates an imperative multicast boundary. Disposal completes subscribers and releases replay and pending values.

initial + replay interaction: When initial is set and replay is omitted, replay defaults to 1 so the initial value is retained. Setting replay: 0 with initial throws RangeError — the initial value would be immediately dropped.

OptionTypeDescription
initialTOptional initial replay value
replaynumberNon-negative retained value count

Structural adapters ​

fromStore() ​

ts
fromStore<T>(source: {
  getSnapshot(): T;
  subscribe(listener: () => void): () => void;
}): Stream<T>

Bridges snapshot-based state without package-specific dependencies. It emits the current snapshot, subscribes, rechecks for a subscription-time change, and reads the latest snapshot after each notification. Snapshot failure terminates without subscribing.

fromSubscribe() ​

ts
fromSubscribe<T>(subscribe: (listener: (value: T) => void) => () => void): Stream<T>

Bridges callback-delivered event values. Registration runs once per Flux subscription and its teardown runs when that subscription closes.

Types ​

ts
type Teardown = () => void;

type Subscription = {
  [Symbol.dispose](): void;
  readonly closed: boolean;
  unsubscribe(): void;
};

type Observer<T> = {
  complete?: () => void;
  error?: (reason: unknown) => void;
  next: (value: T) => void;
};

type SubscribeOptions = { signal?: AbortSignal };

type Sink<T> = {
  complete(): void;
  error(reason: unknown): void;
  next(value: T): void;
};

type Producer<T> = (sink: Sink<T>, signal: AbortSignal) => Teardown | undefined;
type Operator<A = unknown, B = unknown> = (source: Stream<A>) => Stream<B>;

interface Stream<T> {
  subscribe(observer: Observer<T> | ((value: T) => void), options?: SubscribeOptions): Subscription;
}

type OverflowPolicy = 'drop-newest' | 'drop-oldest' | 'error';
type AsyncIterableOptions = { capacity: number; overflow: OverflowPolicy; signal?: AbortSignal };
type TimerOptions = { delay: number; interval?: number };
type FlattenOptions = { concurrency: number; capacity: number };
type RetryOptions = { times: number; delay?: number | ((attempt: number) => number) };
type ToArrayOptions = { maxItems: number; signal?: AbortSignal };
type ValueOptions<T> = { signal?: AbortSignal; defaultValue?: T };
type ChannelOptions<T> = { initial?: T; replay?: number };
type Channel<T> = {
  [Symbol.dispose](): void;
  readonly disposalSignal: AbortSignal;
  dispose(): void;
  readonly disposed: boolean;
  send(value: T): void;
  readonly stream: Stream<T>;
};

Errors ​

FluxError ​

Base Flux error. Use instanceof FluxError to narrow unknown values.

FluxTimeoutError ​

Raised by timeout(). ms contains configured inactivity duration.

FluxEmptyError ​

Raised by first() and last() when the source completes without emitting any value.

FluxCapacityError ​

Raised when a bounded buffer (mergeMap, concatMap, toArray, async iteration) overflows. capacity contains the configured limit.