level-read-stream

Node.js readable streams for iterating keys, values, and entries in abstract-level databases.

Library
npm
v2.0.0
7stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
26/100Needs Attention
Development Activity12
Maintenance20
Community16
Maturity56
Momentum0

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture72
Code Quality78
Innovation75
Learning Curve82

level-read-stream wraps the iterator, keys, and values methods of any abstract-level compatible database in familiar Node.js Readable streams. It ships three focused classes — EntryStream, KeyStream, and ValueStream — so you can pipe database reads directly into standard stream pipelines, async iterators, or third-party stream libraries without hand-rolling iterator-to-stream glue.

Built by the Level collective (maintainers of classic-level, memory-level, and the broader abstract-level ecosystem), the package is a thin, well-tested compatibility layer: it batches reads via nextv() for throughput, respects backpressure through highWaterMark, and closes the underlying iterator automatically on stream end or destroy.

What You Get

  • EntryStream, KeyStream, and ValueStream classes for reading entries, keys, or values respectively
  • Automatic backpressure handling via a configurable highWaterMark buffer (default 1000)
  • Batched reads through the underlying iterator’s nextv() for better throughput than one-at-a-time iteration
  • Automatic iterator cleanup — the underlying iterator is closed when the stream ends or is destroyed
  • First-class TypeScript definitions with generics for key, value, and database types

Common Use Cases

  • Streaming a full database export to a file or HTTP response using pipeline()
  • Building ETL jobs that read from a classic-level or memory-level database and transform records in flight
  • Feeding database contents into existing Node.js stream-based tooling such as CSV writers or compression streams
  • Reading only keys or only values when the full entry isn’t needed, to reduce memory and I/O overhead

Under The Hood

Architecture — The package centers on a single internal base class, LevelReadStream, that extends readable-stream’s Readable in object mode. Its constructor calls db[method](options) (method being ‘iterator’, ‘keys’, or ‘values’) to create an abstract-level iterator, then implements _read(size) by calling the iterator’s nextv(size) to pull a batch of items and push them onto the stream buffer — falling back to a legacy callback-style nextv for older abstract-level versions via the internal kNextvLegacy handler. EntryStream, KeyStream, and ValueStream are thin subclasses that each call the base constructor with a different underlying method and, in EntryStream’s case, reshape [key, value] tuples into { key, value } objects. _destroy(err, callback) closes the iterator before the stream fully tears down, guaranteeing no dangling database handles.

Tech Stack — The only runtime dependency is readable-stream (a userland, browser-compatible implementation of Node’s stream primitives, kept in sync with the ecosystem so the package works consistently across Node versions and bundlers). abstract-level itself is an optional peer dependency, since the package only needs a db argument shaped like an AbstractLevel instance at runtime. TypeScript consumers additionally need @types/readable-stream. The package targets Node >=18 and ships as CommonJS with a hand-written index.d.ts rather than being authored in TypeScript directly.

Code Quality — test.js uses tape against a memory-level database, covering EntryStream/KeyStream/ValueStream output correctness, destroy behavior, and internal event-listener hygiene (via secret-event-listener, which detects listeners left attached after teardown). Linting is enforced with standard, coverage is tracked via nyc/codecov, and docs are checked with hallmark — a disciplined CI setup for a package this small. The source itself is compact (about 120 lines across index.js) and uses Symbols for private internal state, avoiding property collisions with subclasses.

API Design — The public surface is deliberately minimal: three constructors that each take a db and an options object, all of which behave exactly like a standard Node.js Readable — so they compose with pipe(), pipeline(), and for-await-of without any library-specific glue code. The split between EntryStream/KeyStream/ValueStream lets callers opt out of fetching data they don’t need (e.g. KeyStream avoids value lookups), which is a meaningful performance lever on large scans. TypeScript generics on key/value/database types make the streams type-safe for consumers using typed abstract-level implementations, and the README documents both the modern async and legacy callback iterator paths for backward compatibility.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search