Wonka Stream Library
Wonka is a lightweight, capable push and pull stream library designed for TypeScript and Flow, loosely adhering to the callbag specification. Currently at stable version 6.3.6, it provides a functional approach to handling event streams and iterable data sets, offering helpers to create, transform, and consume multiple values over time. The project maintains an active release cadence, with frequent patch updates addressing minor fixes and improvements, and occasional minor versions introducing new features, such as adding the `addOne` argument to `takeWhile` in `v6.3.0`. Its key differentiators include its small bundle size, strong TypeScript integration, and a focus on composing operations through a `pipe` function, offering a pragmatic alternative to larger reactive programming libraries while maintaining clear stream semantics. Version 6 notably shifted its focus exclusively to TypeScript, Flow, and JavaScript environments, dropping support for Reason/OCaml/esy/dune that was present in v5.
Common errors
-
TypeError: require is not a function
cause Attempting to use CommonJS `require()` syntax in an environment where Wonka is distributed as an ESM-only package or when the project's `type` is set to `module` in `package.json`.fixSwitch to ES Module `import` syntax (e.g., `import { pipe } from 'wonka';`). Ensure your project is configured for ESM, or use a bundler that correctly handles module resolution. -
Property 'pipe' does not exist on type 'Source<T>'
cause Misunderstanding Wonka's functional API where `pipe` is a top-level function that composes operations, rather than a method on the source object itself.fixAlways use `pipe()` as a standalone function: `pipe(source, operator1, operator2, ...)`. Do not try to call `source.pipe()`. -
Type 'boolean | undefined' is not assignable to type 'boolean'.
cause This error can occur in versions `<6.2.5` if you explicitly typed an `ObservableSubscription` and then accessed `closed`, as it was optionally `boolean | undefined`. After `v6.2.5`, `closed` became a required `boolean`.fixUpdate to `wonka@6.2.5` or later. If sticking to older versions, adjust your TypeScript types to explicitly allow `boolean | undefined` for `closed` if you're writing custom subscription logic.
Warnings
- breaking Version 6 of Wonka dropped support for Reason/OCaml/esy/dune. Users migrating from v5 who relied on these environments will need to remain on v5 or rewrite their streaming logic for TypeScript/Flow/JavaScript.
- breaking In `v6.2.5`, the `closed` property on `ObservableSubscription`s was made a required boolean field to align with the Observable proposal's type specification. Code expecting `closed` to be optional or `undefined` might encounter TypeScript errors.
- gotcha Prior to `v6.3.4`, there were issues with missing `Symbol.observable` global declarations in typings, which could lead to type errors when integrating with libraries or patterns relying on the TC39 Observable proposal.
- gotcha Early patch versions of `v6.3` (specifically prior to `v6.3.1`) had missing `declare` keywords on internal ambient enums, causing potential compilation issues in some TypeScript environments.
Install
-
npm install wonka -
yarn add wonka -
pnpm add wonka
Imports
- pipe
import pipe from 'wonka'
import { pipe } from 'wonka' - fromArray
const fromArray = require('wonka').fromArray;import { fromArray } from 'wonka' - subscribe
import { Observable } from 'wonka'; new Observable().subscribe();import { subscribe } from 'wonka' - make
import { createSource } from 'wonka'import { make } from 'wonka'
Quickstart
import { pipe, fromArray, map, filter, subscribe, make } from 'wonka';
// 1. Create a simple stream from an array, transform it, and log values
const numberStream = pipe(
fromArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
filter(n => n % 2 === 0), // Keep only even numbers
map(n => n * 2), // Double them
subscribe(value => {
console.log(`Array Stream: ${value}`);
})
);
// For demonstration, manually unsubscribe after some time (optional for finite streams)
// setTimeout(() => numberStream.unsubscribe(), 100);
// 2. Create a custom interval stream that emits a few values
const intervalSource = (intervalMs: number) =>
make<number>(({ next, complete }) => {
let count = 0;
const id = setInterval(() => {
if (count < 3) { // Emit 3 values then complete
next(count++);
} else {
complete(); // Signal completion
clearInterval(id);
}
}, intervalMs);
return () => clearInterval(id); // Teardown logic
});
const intervalPipeline = pipe(
intervalSource(1000), // Emit every second
map(val => `Custom Interval Stream: ${val}`),
subscribe(console.log)
);
// The interval stream will automatically complete and clean up after 3 emissions.