mrkeyoor.com_
Sat 08 Aug 21:59 UTC
npmUtilsupdated 08 Aug 2026

glob-stream

A CommonJS utility that walks the filesystem for one or more glob patterns and exposes matches as a `streamx` readable stream. Each object contains an absolute normalized `cwd`, the non-glob `base`, and the matched `path`; it does not read file contents. Matching is provided by anymatch and picomatch-style options, while pause and resume behavior lets downstream object streams apply backpressure. It is mainly useful inside Gulp-style build pipelines that want file discovery to remain streaming.

Verdict

A dependable adapter when file discovery must feed an existing Gulp or streamx object pipeline. For ordinary scripts that just need path names, a promise-returning glob library is easier to type, test, and clean up.

API stability4/5The central function and `{ cwd, base, path }` output have remained recognizable across the package's long life, and 8.0.3 stays within the version 8 contract introduced in 2023. Major releases have changed internals and runtime floors, including the move to streamx, so consumers should not assume the underlying stream class is node:stream. Within the current major, options and record shape are narrow and predictable.
Docs3/5The README documents every package-specific option, the positive-glob requirement, singular-path error behavior, emitted object fields, and the link to picomatch options. The short usage example is enough for an experienced stream user. It omits complete error-handling and collection examples, TypeScript guidance, ordering and watch limitations, ignore examples, symlink behavior, and the practical difference between streamx and core streams.
Maintenance4/5The Gulp organization published 8.0.3 and pushed the repository on June 1, 2025. The repository is not archived, and GitHub reports 5 open issues and pull requests, a manageable queue for a mature utility. Releases are intentionally infrequent after the 8.0 line, but the dependency refresh in 8.0.3 and continued placement in the Gulp ecosystem show that the package is maintained rather than abandoned.
Ecosystem4/5The package recorded 3,528,512 downloads in the measured npm week and is maintained under gulpjs, where cwd and base records fit established file-pipeline conventions. It composes with streamx and ordinary pipe consumers and delegates matching to the familiar anymatch and picomatch stack. Direct use is narrower than array-oriented glob libraries, and missing bundled types reduces its appeal in current TypeScript projects.

Use it if

  • You are building a Gulp-style object pipeline and need matches to arrive incrementally instead of as one array
  • You need each match labeled with cwd and base so a downstream step can preserve relative directory structure
  • You want positive and negative globs, ignore patterns, dotfile control, and duplicate filtering in one file walker
  • Your downstream code already uses streamx or accepts Node-compatible object streams
Skip it if

Setup reality

Install with `npm install glob-stream`; there are no peer dependencies, credentials, native addons, or configuration files. Version 8 supports Node 10.13 and later and is loaded with require(). The first surprise is the output: matches are plain object-mode records containing absolute, forward-slash-normalized cwd, base, and path values. You must add a read stream if a later transform needs bytes. At least one positive glob is mandatory, so an array containing only `!vendor/**` throws synchronously. A wildcard that matches nothing is allowed, but a literal path that does not exist emits an error by default because the package treats singular paths as promises that one item should exist. Set allowEmpty only when that absence is intentional. Dotfiles are excluded unless dot is true. cwd defaults to the process working directory, which makes CI behavior depend on where the command starts unless you set it explicitly. base defaults to the absolute portion before the first glob token; use base or cwdbase when downstream relative paths must be stable. Matches are deduplicated by path, and uniqueBy can be a property or function. The stream is implemented by streamx rather than node:stream Readable, though ordinary pipe and event consumption work. Its eight runtime dependencies handle walking, matching, normalization, queueing, and absolute-glob conversion. The walker follows directory symlinks only after resolving them and tries to avoid cycles, but large trees are still scanned from each positive glob parent. Errors from readdir or missing singular paths destroy the stream, so attach an error handler or use a pipeline that observes failures. There is no ordering guarantee, no watch behavior, and no content reading hidden behind the API.

Patterns

Stream matching file recordsstream-matches

const globStream = require('glob-stream')

const matches = globStream('src/**/*.js')
matches.on('data', ({ cwd, base, path }) => {
  console.log({ cwd, base, path })
})
matches.on('error', console.error)

The stream emits metadata records, not file contents. All three paths are absolute and normalized to forward slashes.

Combine includes and exclusionsmultiple-patterns

const matches = globStream([
  'src/**/*.{js,ts}',
  '!src/**/*.test.{js,ts}',
  '!src/generated/**',
])

At least one positive pattern is required. An all-negative pattern list throws `Missing positive glob` synchronously.

Resolve globs from a stable project directoryset-cwd

const path = require('node:path')

const matches = globStream('packages/*/src/**/*.ts', {
  cwd: path.resolve(__dirname, '..'),
})

cwd defaults to process.cwd(). Set it explicitly when scripts may be launched from different directories.

Permit an optional singular pathallow-missing-path

const optionalConfig = globStream('config/local.json', {
  allowEmpty: true,
})

Without allowEmpty, a missing non-glob path emits an error. Wildcard patterns are allowed to match zero files by default.

Include dotfiles and dot directoriesinclude-dotfiles

const allConfigs = globStream('**/*', {
  cwd: './config',
  dot: true,
})

dot defaults to false, so entries such as .env and files below .config are otherwise skipped by matching.

Keep exclusions separate with ignoreignore-patterns

const sourceFiles = globStream('src/**/*.js', {
  ignore: ['src/vendor/**', 'src/**/*.generated.js'],
})

ignore accepts a string or array and is normalized relative to cwd and root like the positive globs.

Set the base used for relative destinationspreserve-relative-paths

const path = require('node:path')

const files = globStream('assets/**/*', {
  cwd: __dirname,
  base: path.join(__dirname, 'assets'),
})
files.on('data', (file) => {
  console.log(path.relative(file.base, file.path))
})

base must be an absolute or cwd-resolved string that matches the layout you want downstream. It does not change which files match.

Make cwd and base identicaluse-cwd-as-base

const files = globStream(['images/**', 'styles/**'], {
  cwd: './public',
  cwdbase: true,
})

cwdbase overrides the inferred glob parent. This is useful when several positive globs should share one output root.

Deduplicate by a custom keycustom-deduplication

const path = require('node:path')

const files = globStream(['packages/*/assets/**', 'shared/assets/**'], {
  uniqueBy: (file) => path.basename(file.path).toLowerCase(),
})

The default uniqueBy is `path`. A broad custom key can intentionally discard different files that share the same name.

Match directories rather than their filesmatch-directories

const directories = globStream('packages/*/', {
  cwd: process.cwd(),
})

A trailing slash pattern can match directory records. The emitted object still has only cwd, base, and path, not a Dirent or stat.

Process records with a streamx writablepipe-object-records

const { Writable } = require('streamx')

const sink = new Writable({
  objectMode: true,
  write(file, callback) {
    console.log(file.path)
    callback(null)
  },
})

globStream('src/**/*').pipe(sink)

The readable side is object mode. A byte-oriented writable will reject the emitted plain objects.

Collect the stream into an arraycollect-results

function collect(globs, options) {
  return new Promise((resolve, reject) => {
    const items = []
    globStream(globs, options)
      .on('data', (item) => items.push(item))
      .once('error', reject)
      .once('end', () => resolve(items))
  })
}

const files = await collect('src/**/*.ts')

Result order is not guaranteed. Sort by path after collection when snapshots or reproducible builds require stable ordering.

Alternatives

PackageRegistryPick it when
fast-globnpmYou want fast promise, sync, or Node stream matching with path strings and a broad option set
globbynpmYou want a friendly ESM promise API with gitignore support and sensible multiple-pattern handling
globnpmYou want the established node-glob API, PathScurry objects, async iteration, and traversal controls
tinyglobbynpmYou want a small modern matcher for array results and do not need a streaming object pipeline