mrkeyoor.com_
Wed 23 Sept 00:37 UTC
npmUtilsupdated 22 Sept 2026

@mrmlnc/readdir-enhanced review

@mrmlnc/readdir-enhanced 2.2.1 is a 2018 fork of a recursive Node directory reader. Beyond `fs.readdir`, it supplies blocking, Promise, callback, and object-stream forms; depth controls; glob, RegExp, and function filters; Stats-returning variants; output path rewriting; and injectable filesystem methods. The package on npm is frozen under the @mrmlnc scope, while its repository now documents the later @jsdevtools successor. Read the 2.2.1 tarball's API when maintaining this fork.

Verdict

Our @mrmlnc/readdir-enhanced 2.2.1 install occupied 1 MB and passed npm audit, but its npm scope has been frozen since 2018 and its live repository documents a successor. Keep it only for existing version 2 callers, then migrate to Node core or a maintained walker.

We installed it

Lab card: what happened when we installed @mrmlnc/readdir-enhancedScreenshot of @mrmlnc/readdir-enhanced documentation
Install✓ · 1.7s3 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)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @mrmlnc/readdir-enhanced install cleanly?

Yes. In a fresh container with an empty cache, npm install @mrmlnc/readdir-enhanced finished in 2 seconds, leaving 3 packages and 1 MB on disk. npm audit reported no known vulnerabilities.

Can @mrmlnc/readdir-enhanced 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 @mrmlnc/readdir-enhanced work with both ESM and CommonJS?

Yes. Both import '@mrmlnc/readdir-enhanced' and require('@mrmlnc/readdir-enhanced') worked in Node 22 in our run. The package is published as CommonJS.

Does @mrmlnc/readdir-enhanced include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@mrmlnc/readdir-enhanced or readdirp: which should you use?

readdirp: Use it for a current recursive directory stream with bounded-memory consumption. Our @mrmlnc/readdir-enhanced 2.2.1 install occupied 1 MB and passed npm audit, but its npm scope has been frozen since 2018 and its live repository documents a successor.

When should you not use @mrmlnc/readdir-enhanced?

You are choosing a new walker: this scope has not released since 2018 and the linked project moved to @jsdevtools

API stability3/5The 2.2.1 tarball has a concrete legacy surface covering sync, Promise, callback, stream, Stats, filter, depth, separator, basePath, and filesystem injection calls. No later @mrmlnc release has changed those methods. Package identity weakens that apparent stability: the linked repository continued under another npm scope and introduced APIs such as an iterator and `stats: true` that this release does not share.
Docs2/5The README shipped inside 2.2.1 explains depth values, glob separators, function filters, Stats aliases, stream events, path bases, and custom filesystem methods with many examples. It repeatedly imports the unscoped `readdir-enhanced` name instead of @mrmlnc/readdir-enhanced, and calls its changes only monkey fixes. The current repository README describes @jsdevtools/readdir-enhanced, so readers must separate two package identities before trusting an example.
Maintenance1/5The @mrmlnc line remains at 2.2.1 and its code belongs to a fork whose repository later moved to JS-DevTools. GitHub's last push is 2020-07-28, while the live README and badges point at the successor package rather than new @mrmlnc releases. The repository is open, though that does not provide an update path for this npm scope. Teams should plan around frozen behavior and handle migration themselves.
Ecosystem3/5npm recorded 3,058,028 downloads last week and the redirected GitHub repository has 86 stars, which shows that the family remains embedded in dependency trees. Current documentation, naming, and future-facing APIs center on the @jsdevtools successor. The @mrmlnc artifact has no separate plugin layer or active integration surface, so its ecosystem score comes from installed legacy reach rather than present-day adoption.

Use it if

  • Existing code imports the @mrmlnc scope and calls its version 2 sync, async, stream, or `.stat` aliases
  • A Node 4-compatible dependency needs recursive walking and filters behind an `fs.readdir`-like call
  • Your virtual filesystem can provide `readdir`, `lstat`, and `stat` to the package's injected `fs` option
  • You need object-stream results from this exact legacy API while preparing a controlled migration
Skip it if

Setup reality

We installed @mrmlnc/readdir-enhanced 2.2.1 in our sandbox in 1.7 seconds. It produced 3 packages and 1 MB on disk, and npm audit reported 0 known vulnerabilities. The release is 112 KB unpacked, declares 2 direct dependencies, 0 peers, the MIT license, and Node 4 or newer. No native compilation, credential, or config step was involved.

The package is CommonJS with no exports map. Both require() and ESM import worked in Node 22, and our inspection found bundled TypeScript declarations. The browser build failed, which is expected for a directory walker using Node filesystem calls. Import the exact @mrmlnc name; the README packed in 2.2.1 shows the unscoped package in several examples and can silently lead users to another artifact.

Async and sync calls buffer all results. The stream form emits entries as traversal proceeds and is the safer choice for a large tree. deep defaults off and accepts a boolean, depth, glob, RegExp, or predicate. Function filters and recursion predicates receive Stats objects extended with path and depth, so those modes add metadata work. Glob matching uses forward slashes even on Windows.

Version 2 returns Stats through methods such as async.stat() and stream.stat(); do not copy the successor's stats: true option. basePath changes returned labels without changing the directory read. An injected fs object is merged with Node defaults, so a remote adapter should provide readdir, lstat, and stat together. Deep traversal follows directory symlinks and does not track visited inodes, making cycle prevention the caller's job.

Patterns

Read one directory with a Promise read-async

const readdir = require('@mrmlnc/readdir-enhanced');
const entries = await readdir('./src');

The default async call buffers every result before its Promise resolves.

Use the callback alias read-callback

readdir.async('./src', (error, entries) => {
  if (error) throw error;
  console.log(entries);
});

The callback changes result delivery only; traversal still buffers the full array.

Read a small startup directory synchronously read-sync

const entries = readdir.sync('./templates');

`sync()` blocks the Node thread until all selected entries have been read and buffered.

Traverse all descendant directories walk-recursively

const entries = await readdir('./src', { deep: true });

Directories and files are both returned. Directory symlinks are followed without cycle detection.

Stop after two directory levels limit-depth

const entries = await readdir('./src', { deep: 2 });

Depth is counted below the starting path. Negative and fractional depth values are invalid.

Find package manifests filter-glob

const files = await readdir('.', {
  deep: true,
  filter: '**/package.json'
});

Glob strings always use forward slashes, including on Windows. Filtering does not stop traversal into unmatched directories.

Avoid entering node_modules prune-directory

const files = await readdir('.', {
  deep: stat => !stat.path.split(/[\\/]/).includes('node_modules')
});

Use the `deep` predicate to prevent traversal. A result filter can hide a directory after the walker already entered it.

Request Stats objects with the version 2 API return-stats

const stats = await readdir.async.stat('./uploads', { deep: 1 });
for (const stat of stats) console.log(stat.path, stat.depth, stat.size);

In 2.2.1, `.stat()` variants return Stats. The successor's `stats: true` form is a different API.

Consume a large walk as a stream stream-tree

const walk = readdir.stream('./archive', { deep: true });
walk.on('data', entry => processEntry(entry));
walk.on('error', error => console.error(error));

A data listener starts flowing consumption. Always attach an error listener before traversal reaches inaccessible paths.

Label results with an absolute base absolute-results

const path = require('node:path');
const root = path.resolve('./assets');
const entries = await readdir(root, { basePath: root });

`basePath` prefixes output strings. It does not change which root the package opens.

Walk a virtual filesystem inject-filesystem

const entries = await readdir('/virtual', {
  deep: true,
  fs: {
    readdir: vfs.readdir.bind(vfs),
    lstat: vfs.lstat.bind(vfs),
    stat: vfs.stat.bind(vfs)
  }
});

Overrides merge with Node's local fs methods. Supply all three calls to avoid mixing virtual paths with local metadata.

Alternatives

PackageRegistryPick it when
readdirpnpmUse it for a current recursive directory stream with bounded-memory consumption.
fast-globnpmUse it when matching glob patterns is the main job rather than emulating readdir.
globbynpmUse it for higher-level glob searches with ignore patterns and modern Promise APIs.

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.