wonka
A tiny but capable push and pull stream library for TypeScript
Repository Health
Technical Analysis
Wonka is a lightweight stream library for TypeScript and Flow, loosely based on the callbag spec, that unifies push-based (observable-like) and pull-based (iterable-like) streams behind one small set of primitives: sources, operators, and sinks. It ships composable operators for mapping, filtering, combining, debouncing, and buffering streams, along with sinks like subscribe, toPromise, and toArray to consume them.
Wonka is best known as the streaming engine underneath the urql GraphQL client, where it powers the exchange pipeline that request, cache, and network operations flow through, but it works standalone for any event-stream or async-iterable use case that needs a minimal footprint.
What You Get
- A
pipe()function for composing sources through a chain of operators into a sink, similar to RxJS but with a much smaller bundle size - Stream-creation helpers like
fromArray,fromValue,fromPromise,fromIterable,interval,subject, andmake - A large operator library covering
map,filter,merge,combine,switchMap,debounce,buffer,takeUntil,share, and dozens more - Sinks for consuming streams as callbacks, Promises, arrays, or async iterables (
subscribe,toPromise,toArray,toAsyncIterable) - Full TypeScript types and a Flow type definition (
index.js.flow) for teams on either type system
Common Use Cases
- Powering an exchange/middleware pipeline for a GraphQL or HTTP client (as
urqldoes) where requests flow through composable transform stages - Coordinating async UI state (loading, debounced search input, cancellable requests) without pulling in the full RxJS library
- Bridging between push-based event sources and pull-based async iteration in the same codebase
- Building custom reactive data pipelines where bundle size matters more than the full RxJS operator surface
Under The Hood
Architecture — Wonka’s core model is a callbag-style function contract: a Source<T> is a function that accepts a Sink, and a Sink is a function that receives SignalKind-tagged push/pull/end signals; pipe() (src/pipe.ts) threads a source through a chain of Operator functions before handing it to a terminal sink, and helpers.ts centralizes the low-level push/start/teardown signal plumbing shared by every source and operator. Tech Stack — Pure TypeScript with a Flow type-definition file for interop, built with Rollup (scripts/rollup.config.mjs) into CJS/ESM/type-only outputs, tested with Vitest, and versioned via Changesets; it has zero runtime dependencies. Code Quality — The operator surface (src/operators.ts, ~1,460 lines) and sources module (src/sources.ts, ~400 lines) are both extensively TSDoc-commented with @example blocks, and are backed by a dedicated __tests__ suite including a compliance.ts harness that checks operators against the callbag spec’s signal contract. API Design — The pipe(source, operator1, operator2, ..., sink) shape mirrors RxJS closely enough to be familiar, while staying tree-shakeable and dependency-free; the tradeoff is that its lower-level, signal-based mental model (push/pull/end via SignalKind) takes more upfront learning than a plain Promise or EventEmitter API.
Used by 3 apps in this directory
GraphQL Hive
Developer Tools · Devops · Monitoring
Open-source GraphQL schema registry and observability platform with breaking change detection, federation support, and CI/CD integration for teams of any size.
Hoppscotch
Developer Tools
A lightweight, offline-capable API development ecosystem for testing HTTP, GraphQL, WebSocket, MQTT, and SSE endpoints across web, desktop, and CLI.
Tabby
AI Code Assistants
Self-hosted AI coding assistant — run GitHub Copilot-grade code completion on your own hardware with no cloud dependency.