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

node-readfiles review

node-readfiles 0.4.0 is supposed to traverse a directory, read matching files one at a time, call a handler with each path, body, and stat object, then resolve with the collected filenames. Its options cover traversal depth, dotfiles, order, text encoding, relative or full paths, and a small home-grown filter syntax. The published package does not reach that API on current Node. In our Node 22 sandbox, both `require('node-readfiles')` and ESM `import` failed because the CommonJS package's main file contains AMD `define(...)` wrappers. That packaging break is the reason to avoid it, regardless of its 4.6 million weekly downloads.

Verdict

node-readfiles 0.4.0 installed in 0.9 seconds, but both `require()` and ESM `import` failed on Node 22.23.2 in our sandbox because the published main file is AMD output. Do not install it for new code; replace direct use, or identify and upgrade the transitive parent.

We installed it

Lab card: what happened when we installed node-readfilesScreenshot of node-readfiles documentation
Install✓ · 0.9s1 package on disk · 1 MB
ImportESM import fails · require() fails · CommonJS package
Browser3.7 KBgzipped (16.1 KB minified), bundled with esbuild
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does node-readfiles install cleanly?

Yes. In a fresh container with an empty cache, npm install node-readfiles finished in 0.9s, leaving 1 package and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does node-readfiles add to a browser bundle?

3.7 KB gzipped (16.1 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does node-readfiles work with both ESM and CommonJS?

Neither plain import nor require succeeded in our sandbox, so it needs a bundler or extra setup.

Does node-readfiles include TypeScript types?

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

node-readfiles or readdirp: which should you use?

readdirp: Choose it for recursive file entries, depth limits, and explicit file or directory filters. node-readfiles 0.4.0 installed in 0.9 seconds, but both require() and ESM import failed on Node 22.23.2 in our sandbox because the published main file is AMD output.

When should you not use node-readfiles?

You need to import the public package; Node 22.23.2 failed on both require() and ESM import in our sandbox

API stability1/5A stable API must be reachable from the published entry point, and version 0.4.0 fails that basic test. package.json declares a CommonJS main file without an exports map, while the emitted JavaScript expects an AMD `define` function. Both Node loading styles failed in our run before `readfiles` could be called. The documented callback and Promise shapes therefore provide no usable compatibility guarantee for package consumers.
Docs2/5The README explains depth values, hidden-file defaults, encodings, filename formats, reverse order, error handling, its 3 wildcard forms, and the unusual callback that returns a `next` function. Those examples are detailed enough to plan a migration. The page never warns that version 0.4.0 cannot load in ordinary Node, and it does not spell out symlink-cycle behavior or offer current TypeScript declarations.
Maintenance2/5The repository is unarchived, and both version 0.4.0 and the last push date are January 9, 2026. GitHub reports 7 stars and 3 open issues and pull requests. Recent publication is better than a long-abandoned tarball, but this release shipped an entry file that fails before user code runs. That points to missing consumer smoke tests in the release process, which outweighs the recent timestamp.
Ecosystem2/5npm counted 4,655,192 downloads in the latest completed week, yet GitHub shows only 7 stars and the current package cannot be loaded through either Node module style in our sandbox. That mismatch suggests much of the volume is transitive or pinned usage, although the download source does not identify parents. There is no adapter or plugin layer, and native filesystem APIs plus established glob packages cover the same traversal jobs.

Use it if

  • You are tracing a transitive dependency and need to reproduce why version 0.4.0 crashes before returning its API
  • A private fork already recompiles the source correctly and legacy code depends on its callback and Promise contract
  • You are mapping old `depth`, `filter`, `hidden`, or `filenameFormat` behavior before replacing the package
  • An audit needs evidence from the published tarball instead of assuming its high download count means the entry point works
Skip it if

Setup reality

Our node-readfiles 0.4.0 install completed in 0.9 seconds in a fresh Node 22 container. It left 1 package and 1 MB on disk, with 0 known vulnerabilities from npm audit. The package has 0 direct dependencies and 0 peers and is 168 KB unpacked. It declares CommonJS and has no exports map. Both require() and ESM import failed under Node 22.23.2. No TypeScript types were found. Esbuild still emitted a 16.1 KB minified, 3.7 KB gzipped browser bundle, which does not make the Node entry point usable.

There are no credentials, native builds, or configuration files. Installation succeeds because npm does not execute the broken entry file. The crash appears on first load: package.json points to lib/readfiles.js, whose AMD define(...) calls have no loader in ordinary Node. Dynamic import reaches the same incompatible output. This is a publication defect, so adding an application option cannot fix it.

Even a locally rebuilt copy has dated behavior to review. The README says file traversal is sequential, UTF-8 content is read by default, dot-prefixed names are excluded, and filters understand only ?, *, and **. A callback may return another function and must call next() after asynchronous work. Missing that call leaves the outer Promise waiting, with no built-in timeout or concurrency cap.

Prefer readdir({recursive: true}) for a small native solution or a maintained walker for filters and symlink policy. If 0.4.0 arrives transitively, use npm explain node-readfiles before adding an override because removing the package may require upgrading its parent. The 3.7 KB gzipped esbuild result is beside the point for a utility that describes itself as a Node directory reader and fails in Node.

Patterns

Reproduce the package failure reproduce-load-failure

node -e "require('node-readfiles')"
# ReferenceError: define is not defined

Version 0.4.0 throws before returning a function; this is the published artifact's behavior.

Locate the declared main file inspect-entry-file

node -e "const p=require('node-readfiles/package.json'); console.log(p.version, p.main)"
# 0.4.0 lib/readfiles.js

The file exists, but its AMD wrapper is incompatible with the CommonJS declaration.

Find who installed the package find-transitive-parent

npm explain node-readfiles
npm ls node-readfiles

Run both commands before overriding 0.4.0 so the parent dependency and every installed path are visible.

List files with Node's filesystem API replace-native-recursion

import {readdir} from 'node:fs/promises';
const entries = await readdir(root, {recursive: true, withFileTypes: true});
const files = entries.filter(entry => entry.isFile());

Native recursive reading removes 1 broken package, but your code must decide path formatting and symlink policy.

Read selected text files replace-content-reading

import {readFile, readdir} from 'node:fs/promises';
import {join} from 'node:path';
const names = await readdir(root);
const rows = await Promise.all(names.filter(x => x.endsWith('.txt')).map(async x => [x, await readFile(join(root, x), 'utf8')]));

`Promise.all` reads concurrently, unlike the package's serial callback flow; add a limiter for large directories.

Use documented glob matching replace-glob-filter

import fg from 'fast-glob';
const files = await fg('**/*.txt', {cwd: root, dot: false, onlyFiles: true, followSymbolicLinks: false});

This makes dotfile and symlink behavior explicit instead of relying on the package's 3 wildcard forms.

Limit recursion with readdirp replace-depth-limit

import {readdirpPromise} from 'readdirp';
const entries = await readdirpPromise(root, {depth: 1, type: 'files', fileFilter: '*.txt'});
const files = entries.map(entry => entry.path);

A depth of 1 allows one nested directory level while returning entry metadata.

Preserve one-at-a-time handling process-sequentially

for (const filename of files) {
  const body = await readFile(filename, 'utf8');
  await processFile(filename, body);
}

This explicit loop matches serial processing without requiring a callback to call `next()`.

Record failures and continue continue-after-error

const failures = [];
for (const filename of files) {
  try { await processFile(filename); }
  catch (error) { failures.push({filename, error}); }
}

Every captured error retains its filename, unlike swallowing failures behind a broad continue option.

Make hidden-file policy visible exclude-dotfiles

const visible = entries.filter(entry => !entry.name.startsWith('.'));

The old package excludes dot-prefixed basenames by default; preserve or change that rule deliberately during migration.

Alternatives

PackageRegistryPick it when
readdirpnpmChoose it for recursive file entries, depth limits, and explicit file or directory filters.
fast-globnpmChoose it for mature glob syntax, ignore rules, and configurable symlink traversal.
globbynpmChoose it for a Promise API around multiple glob patterns and ignore files.

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.