node-readfiles
node-readfiles is intended to walk a Node.js directory tree sequentially, optionally filter relative paths, read each file, invoke a callback with its name, contents, and stat, then resolve a Promise with all matched names. It has options for depth, dotfiles, reverse traversal, output path format, encoding, and continuing after filesystem errors. That intended API is compact, but the current 0.4.0 npm package is not loadable by ordinary Node: its declared main file was compiled as AMD and calls an undefined define function.
Do not install node-readfiles 0.4.0: the published entry point cannot load in Node, and its declarations are malformed for package consumers. Use native recursive readdir for simple code or readdirp, fast-glob, or globby when filtering and traversal behavior matter.
Use it if
- You are auditing an existing dependency tree and need to understand why node-readfiles 0.4.0 fails during module loading
- You maintain a patched or privately rebuilt fork that emits CommonJS correctly and already relies on the callback-plus-Promise traversal contract
- You need to migrate legacy code that uses its filter, depth, filename format, or per-file callback options to a maintained walker
- You are evaluating whether millions of weekly downloads represent a safe direct dependency and want the answer grounded in the published tarball
- You need a package that can be imported: requiring the published 0.4.0 entry point throws ReferenceError: define is not defined because the build contains AMD wrappers
- You need dependable TypeScript declarations: the published declaration file uses ambient module names such as src/readfiles and includes test modules instead of declaring the node-readfiles package cleanly
- You need parallel traversal or a concurrency limit: the implementation advances one file at a time and waits for each content read and callback before continuing
- You need full glob semantics or case-sensitive matching: its custom filter compiler supports only ?, *, and ** and always creates a case-insensitive regular expression
- You need protection from symlink directory cycles: the implementation uses fs.stat, follows links, and does not track visited real paths
Setup reality
npm install node-readfiles@0.4.0 completes because there are no runtime dependencies, peer dependencies, native builds, credentials, or config files. The failure happens on the first import. The package.json main field is lib/readfiles.js, and the published file is a TypeScript outFile containing AMD define(...) modules. Node does not install an AMD loader for CommonJS packages, so require('node-readfiles') throws ReferenceError: define is not defined before any API is returned. Dynamic import does not repair that packaging mismatch. The published lib/readfiles.d.ts has the same build-shape problem: it declares internal modules named src/build-filter, src/readfiles, and test fixtures rather than a normal external node-readfiles module. Even after rebuilding the source as CommonJS, there are operational surprises. Traversal is serial, defaults to reading every file as UTF-8, excludes every basename beginning with a dot, follows symlinks through fs.stat, and has no visited-path protection. Filter patterns are converted by a small custom regex builder rather than a standard glob engine and matching is always case-insensitive. Setting rejectOnError to false continues, but read failures are not passed to the callback in the same way stat failures are. The source also exposes an undocumented async option that prevents automatic progress unless callback code arranges to call next; a mistaken setting can leave the returned Promise pending forever. A recent version number does not offset a broken entry point, so replacement is safer than a production workaround.
Patterns
Confirm the 0.4.0 load failurereproduce-entrypoint-failure
node -e "require('node-readfiles')"
# ReferenceError: define is not definedThis is the expected result from the published 0.4.0 tarball, not an application configuration error.
Check which file Node loadsinspect-published-main
node -e "const p=require('node-readfiles/package.json'); console.log(p.version, p.main)"
# 0.4.0 lib/readfiles.jsThe target exists, but its top-level AMD define calls are incompatible with Node's CommonJS loader.
List files with native recursive readdirreplace-basic-recursion
import {readdir} from 'node:fs/promises';
const entries = await readdir('/path/to/dir', {
recursive: true,
withFileTypes: true,
});
const files = entries
.filter(entry => entry.isFile())
.map(entry => `${entry.parentPath}/${entry.name}`);Native recursive readdir avoids this package entirely but requires a Node version that supports recursive directory reads and parentPath on Dirent.
Read matched files with native promisesreplace-content-reading
import {readFile, readdir} from 'node:fs/promises';
import {join} from 'node:path';
const names = await readdir('/path/to/dir');
const text = await Promise.all(
names.filter(name => name.endsWith('.txt'))
.map(async name => [name, await readFile(join('/path/to/dir', name), 'utf8')]),
);Promise.all reads concurrently, unlike node-readfiles' serial traversal. Add a limiter when the directory may contain many files.
Match recursive files with fast-globreplace-glob-filtering
import fg from 'fast-glob';
const files = await fg('**/*.txt', {
cwd: '/path/to/dir',
dot: false,
onlyFiles: true,
followSymbolicLinks: false,
});This replaces the package's custom ?, *, and ** filter with documented glob semantics and makes symlink handling explicit.
Limit traversal depth with readdirpreplace-depth-limit
import {readdirpPromise} from 'readdirp';
const entries = await readdirpPromise('/path/to/dir', {
depth: 1,
type: 'files',
fileFilter: '*.txt',
});
const files = entries.map(entry => entry.path);readdirp exposes depth and filtering directly and returns entry metadata rather than combining traversal with content reads.
Exclude dotfiles explicitlyreplace-hidden-file-policy
import {readdirpPromise} from 'readdirp';
const entries = await readdirpPromise(root, {
directoryFilter: entry => !entry.basename.startsWith('.'),
fileFilter: entry => !entry.basename.startsWith('.'),
});node-readfiles excludes dot-prefixed basenames by default. Making that rule explicit avoids surprising omissions during migration.
Preserve sequential callback processingprocess-files-sequentially
import {readFile} from 'node:fs/promises';
for (const filename of files) {
const content = await readFile(filename, 'utf8');
await processFile(filename, content);
}This matches the intended one-at-a-time behavior without the package's callback-that-returns-another-callback protocol.
Collect per-file errors without abortingcontinue-after-read-error
const failures = [];
for (const filename of files) {
try {
await processFile(filename);
} catch (error) {
failures.push({filename, error});
}
}
if (failures.length) console.error(failures);This is an explicit replacement for rejectOnError: false and retains the filename for every failure.
Find which dependency installed itaudit-transitive-version
npm explain node-readfiles
npm ls node-readfilesA high download count can come from transitive consumers. These commands identify the parent package before you replace or override it.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| readdirp | npm | Choose it for a maintained recursive directory stream with file and directory filters plus explicit depth control |
| fast-glob | npm | Choose it when mature glob syntax, ignore patterns, symlink controls, and high-throughput matching matter |
| globby | npm | Choose it for a friendly Promise API around glob patterns, ignore files, and common filesystem matching tasks |