mrkeyoor.com_
Wed 23 Sept 02:53 UTC
npmUtilsupdated 22 Sept 2026

peek-stream review

peek-stream 1.1.3 is a CommonJS Transform that reads the first line of a Node stream, passes that sample to your selector, and swaps in the parser returned through an error-first callback. It then replays the sampled bytes and any remaining part of the chunk into that parser. This lets a pipeline choose CSV, newline-delimited JSON, or another line-recognizable format while preserving streaming. Version 1.1.3 replaced the deprecated Buffer constructor with `buffer-from`; that March 2018 release is still the newest package. Detection rules and parsers are entirely your code.

Verdict

peek-stream 1.1.3 installed in 1.3 seconds but pulled in 17 packages, shipped no types, and failed our browser build; it remains acceptable inside a tested CommonJS stream pipeline that already depends on its swap contract. New code can usually own the small prefix-buffering transform and avoid relying on an unreleased codebase from 2018.

We installed it

Lab card: what happened when we installed peek-streamScreenshot of peek-stream documentation
Install✓ · 1.3s17 packages on disk · 1 MB
ImportESM import works · require() works · CommonJS package
Browsern/acould not be bundled for the browser (Node-only code, most likely)
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does peek-stream install cleanly?

Yes. In a fresh container with an empty cache, npm install peek-stream finished in 1 seconds, leaving 17 packages and 1 MB on disk. npm audit reported no known vulnerabilities.

Can peek-stream run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does peek-stream work with both ESM and CommonJS?

Yes. Both import 'peek-stream' and require('peek-stream') worked in Node 22 in our run. The package is published as CommonJS.

Does peek-stream include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

peek-stream or through2: which should you use?

through2: Use it when a small custom prefix buffer is easy to own and exact framing behavior matters. peek-stream 1.1.3 installed in 1.3 seconds but pulled in 17 packages, shipped no types, and failed our browser build; it remains acceptable inside a tested CommonJS stream pipeline that already depends on its swap contract.

When should you not use peek-stream?

New maintenance is required. The last default-branch code commit and npm release both date to March 2018.

API stability4/5The package has exposed one function with the same options and callback shape since 2014: inspect a sample, then swap in a duplex parser or return an error. Numeric `maxBuffer` shorthand, line mode, strict mode, and object-mode behavior all remain in a short source file. Existing callers are unlikely to see an upstream change. That predictability comes from 8 years without a release, so newer Node stream behavior is not being exercised by current package maintenance.
Docs2/5The README gives complete CSV and newline-delimited JSON examples, states the default 65,535-byte cap, and explains `maxBuffer` plus strict mode. It omits the `newline: false` source option, object-mode behavior, end-of-input selection, replay of sampled bytes, error propagation, and the requirement that the chosen parser provide both sides of a duplex stream. Safe production use still requires reading the 59-line implementation.
Maintenance1/5peek-stream 1.1.3 was published on March 21, 2018, and the latest default-branch commit is the matching version bump after adopting `buffer-from`. The repository is not archived and has 4 open issues and pull requests, but its 2023 push timestamp reflects later branch activity rather than merged package code. No release has updated through2, duplexify, module exports, declarations, or tests for current Node versions.
Ecosystem3/5npm recorded 3,889,928 downloads from August 18 through August 24, 2026, while GitHub reports 58 stars. The high install count mainly signals old transitive trees. Any Node duplex parser can be selected, and the README demonstrates csv-parser plus ldjson-stream. There is no dedicated plugin layer, TypeScript support, ESM build, or active community surface around the package itself.

Use it if

  • A classic Node stream can choose its parser reliably from the first line or a fixed byte prefix.
  • The input must stay streaming instead of being collected in memory before format selection.
  • An existing CommonJS pipeline already uses through2-style transforms and callback error handling.
  • Parser selection may complete asynchronously and can always call the supplied swap callback.
Skip it if

Setup reality

We installed peek-stream 1.1.3 in a fresh Node 22 Bookworm sandbox in 1.3 seconds. It left 17 packages and 1 MB on disk, while peek-stream itself was 32 KB unpacked. npm audit reported 0 known vulnerabilities. The package declares 3 direct dependencies and 0 peers, uses the MIT license, and has no TypeScript declarations. It is CommonJS without an exports map; both require() and ESM import worked in our checks.

No native build, credentials, or config file is involved. The selected parser is your dependency and must act as both a readable and writable stream. The callback receives the first-line Buffer and a swap(error, parser) function. Call swap once. peek-stream writes the sample into the chosen parser after the callback, so forwarding the same Buffer yourself duplicates the beginning. An asynchronous decision is allowed, but input remains pending until the callback arrives.

By default the stream waits for LF and buffers up to 65,535 bytes. With strict: false, reaching that limit calls the selector even when no newline appeared; with strict: true, it emits No newline found. Strict mode raises the same error if input ends first. The source also supports undocumented newline: false, which waits for the byte cap or end rather than scanning lines. A first object-mode chunk bypasses byte buffering and selects immediately.

Use stream.pipeline() or attach an error listener because selector failures and framing errors leave through the returned duplex. Ambiguous commas, a byte-order mark, comments, and corrupt first records need explicit rules in your detector. Our esbuild browser bundle failed, matching Node-only code. Although GitHub shows a 2023 repository push timestamp, the default branch's newest commit is the 1.1.3 release from 2018; later pull-request activity did not produce a package update.

Patterns

Choose CSV or newline-delimited JSON select-line-format

const peek = require('peek-stream')
const csv = require('csv-parser')
const ldjson = require('ldjson-stream')

const parser = peek((sample, swap) => {
  const line = sample.toString('utf8')
  if (line.trimStart().startsWith('{')) return swap(null, ldjson())
  if (line.includes(',')) return swap(null, csv())
  swap(new Error('unsupported input format'))
})

peek-stream supplies no format test. Check the more specific signature first because valid JSON text can contain commas.

Collect pipeline errors in one callback pipe-errors

const { pipeline } = require('node:stream')

pipeline(source, parser, destination, (error) => {
  if (error) console.error('parse failed:', error.message)
})

`pipeline()` catches source, selector, parser, and destination failures more reliably than a bare chain of `pipe()` calls.

Set a smaller detection buffer cap-sample

const parser = peek({ maxBuffer: 8192 }, (sample, swap) => {
  swap(null, chooseParser(sample))
})

Without strict mode, 8,192 buffered bytes trigger the selector even if no LF has arrived.

Reject an unterminated first record require-newline

const parser = peek(
  { maxBuffer: 8192, strict: true },
  (sample, swap) => swap(null, chooseParser(sample))
)

Strict mode emits `No newline found` at the byte cap and when the source ends before LF.

Inspect fixed-position magic bytes peek-fixed-prefix

const parser = peek(
  { maxBuffer: 16, newline: false },
  (prefix, swap) => swap(null, parserForMagicBytes(prefix))
)

`newline: false` exists in 1.1.3 source but not its README. Selection waits for 16 bytes or the end of input.

Resolve the parser asynchronously select-parser-async

const parser = peek((sample, swap) => {
  lookupParser(sample).then(
    selected => swap(null, selected),
    error => swap(error)
  )
})

The writable side stays blocked until `swap()` runs. Forward promise rejection or a failed lookup can leave the pipeline waiting forever.

Fail on unknown magic bytes reject-unknown-format

const parser = peek({ maxBuffer: 4, newline: false }, (sample, swap) => {
  const magic = sample.toString('hex')
  if (magic === '504b0304') return swap(null, unzipParser())
  swap(new Error(`unsupported magic: ${magic}`))
})

An error passed to `swap()` is emitted by the returned duplex. Add an error handler or use `pipeline()`.

Let the wrapper replay inspected bytes avoid-sample-duplication

const parser = peek((sample, swap) => {
  console.log('selected from', sample.length, 'bytes')
  swap(null, createParser())
})

Do not write `sample` to the parser yourself. Version 1.1.3 forwards the sample and the rest of its original chunk after swapping.

Make empty input an explicit error handle-empty-source

const parser = peek((sample, swap) => {
  if (sample.length === 0) return swap(new Error('empty input'))
  swap(null, chooseParser(sample))
})

With strict mode off, ending before any bytes calls the selector with an empty Buffer.

Select from the first object route-object-mode

const parser = peek((first, swap) => {
  const selected = first.type === 'event'
    ? eventTransform()
    : fallbackTransform()
  swap(null, selected)
})

objectSource.pipe(parser).pipe(objectDestination)

A non-Buffer, non-string first chunk selects immediately. The returned transform must accept and emit matching object-mode values.

Alternatives

PackageRegistryPick it when
through2npmUse it when a small custom prefix buffer is easy to own and exact framing behavior matters.
streamxnpmUse it as the maintained stream base for a new high-throughput detector and parser pipeline.
readable-streamnpmUse it when broad Node stream compatibility matters more than dynamic parser swapping.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.