Skip to content
CAI
Software that uses CAICheck a score

jprichardson/node-fs-extra

63.8

Adequate · 2 October 2026

1.5k

lines of production code

JavaScript

primary language

2

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is a Node.js filesystem utility library that extends the native fs module with higher-level operations for copying, moving, removing, and managing files and directories. It provides both synchronous and asynchronous APIs, including promise-based support and ES module compatibility, to handle common tasks like ensuring directory existence, reading/writing JSON, and recursively emptying directories. The library modernizes its implementation by replacing legacy dependencies with native Node.js methods and standard utilities, ensuring cross-platform consistency and robust error handling.

How it got here

2011–2015 — ESM migration and native refactoring

22 changes.

This period focused on modernizing the fs-extra codebase by migrating to ES Modules and replacing legacy dependencies with native Node.js filesystem methods. The CoffeeScript implementation was removed in favor of JavaScript, and core functions like copy, mkdirs, and remove were refactored to use built-in APIs for improved performance and reliability. Comprehensive test suites were added to verify the new behavior and ensure cross-platform consistency.

2017–2021 — Promise support and API modernization

4 changes.

The project rewrote the core file system module to wrap native methods with universalified callbacks, enabling both callback and Promise-based APIs. This period focused on modernizing specific functions like outputFile to use async/await and ensuring comprehensive test coverage for the new promise-based interfaces and behavioral changes.

Features

Added ESM module support

The library now supports ES Modules (ESM) alongside CommonJS. A new \lib/esm.mjs\ file provides named exports for all fs-extra methods (such as \copy\, \mkdirs\, \readJson\, \pathExists\, etc.) and a default export containing the full API, allowing users to import the library using standard ES module syntax. This change is accompanied by the removal of the legacy CoffeeScript implementation (\lib/copy.coffee\) in favor of the new JavaScript structure.

lib · high confidence

Behavioural changes

Adopts native fs.rm for file removal

The remove functionality now uses Node.js's native fs.rm and fs.rmSync methods instead of the previous rimraf-based implementation. This change simplifies the codebase by removing the rimraf dependency for this specific operation and aligns the behavior with modern Node.js standards, requiring Node.js v14.14 or later.

lib/remove · high confidence

Improved file operation safety and cross-platform consistency

The library now handles edge cases in file moves and copies more robustly. It supports changing file case on case-insensitive systems (like Windows and APFS) by detecting cosmetic renames, preventing unnecessary errors. It also fixes a bug where moving files into a symlinked destination ancestor was incorrectly treated as moving into a subdirectory. Additionally, file timestamp updates (utimes) now properly close file descriptors even if errors occur, preventing resource leaks.

lib/util · high confidence

Parallel removal of directory contents in emptyDir

The emptyDir function now removes items in a directory in parallel using Promise.all, rather than sequentially, which improves performance for directories with many files. The implementation also ensures that if the target directory does not exist, it is created before proceeding, and properly propagates read errors.

lib/empty · high confidence

Refactor move to use fs.rename with cross-device fallback

The move operation now prioritizes the native fs.rename system call for performance, falling back to a copy-then-remove strategy only when moving across different devices (EXDEV error). This change introduces support for preserving timestamps during cross-device moves and adds logic to prevent creating parent directories if the destination is the root path. The API remains compatible, accepting both 'overwrite' and legacy 'clobber' options, and handles case-changing moves on case-insensitive file systems.

lib/move · high confidence

Refactor outputFile to use async/await and modernize structure

The \outputFile\ API in \lib/output-file\ has been refactored to use native async/await instead of callbacks, while maintaining backward compatibility through the \universalify\ wrapper. The implementation now explicitly checks for directory existence using \pathExists\ before creating directories with \mkdirs\, ensuring robust file output behavior. A synchronous counterpart \outputFileSync\ is also provided. Tests confirm that both async and sync versions correctly create files and directories as needed, and overwrite existing files.

lib/output-file · high confidence

Refactored copy and copySync to use native fs methods and async iteration

The copy and copySync functions have been rewritten to leverage native Node.js capabilities: the async copy now uses fs.copyFile and fs.opendir for directory traversal, while the sync version uses fs.copyFileSync and fs.opendirSync. This refactoring improves performance and reliability, particularly for directory copying, and ensures consistent behavior across both synchronous and asynchronous APIs. The implementation also includes better handling of symlinks, file permissions, and timestamps, with specific warnings for 32-bit Node.js environments when preserving timestamps.

lib/copy · high confidence

Refactored ensure functions to use async/await and universalify

The ensure module (lib/ensure) has been refactored to use async/await and the universalify library, providing both promise-based and synchronous versions of ensureFile, ensureLink, and ensureSymlink. This change improves code consistency and performance by leveraging modern JavaScript features. The refactoring also includes updates to symlink path resolution and type detection, ensuring more robust handling of relative and absolute paths.

lib/ensure · high confidence

Restructured JSON module with universalified async methods

The lib/json module has been refactored to use universalify for async methods, ensuring consistent promise-based behavior for outputJson. The module now exports readJson, writeJson, and outputJson (along with their sync counterparts) by wrapping underlying jsonfile operations. This change introduces a breaking change where spaces are no longer used for JSON writing by default, removing the global setting that previously controlled indentation.

lib/json · high confidence

Switch mkdirs implementation to native fs.mkdir recursive

The mkdirs module now uses the native Node.js fs.mkdir with the recursive option instead of the previous make-dir fork. This change simplifies the implementation by relying on built-in filesystem capabilities, while maintaining the same API surface including mkdirs, mkdirp, and ensureDir aliases. The implementation includes path validation for Windows systems to prevent invalid characters in directory paths.

lib/mkdirs · high confidence

fs-extra now wraps native fs methods with universalified callbacks and returns objects for read/write operations

The lib/fs module has been rewritten to wrap standard Node.js fs methods using the universalify library, allowing them to accept either a callback or return a Promise. Notably, fs.read(), fs.write(), fs.readv(), and fs.writev() now return objects containing the bytes read/written and the buffer, rather than just the byte count, which is a breaking change for code expecting the native return signature. The module also conditionally wraps fs.realpath.native if available, emitting a warning if it is not.

lib/fs · high confidence

fs-extra v11.4.1 release and repository restructuring

This update releases fs-extra version 11.4.1, which includes fixes for handling read errors in \emptyDir\*()\, allowing filename renaming with only Unicode normalization differences (APFS-specific), and correcting error handling for symlinks. The repository has been restructured to drop the legacy CoffeeScript implementation (\index.coffee\ removed) and AsciiDoc documentation (\README.asciidoc\ removed), replacing them with a modern Markdown README and a new ESM test suite (\test.mjs\) to verify export consistency. Additionally, a \.npmrc\ file was added to disable package-lock generation, and the \.gitignore\ was updated to exclude coverage and IDE files.

(repo-wide) · high confidence

Test coverage

Added comprehensive test suite for mkdirs functionality; Added test coverage for JSON file operations; Added test coverage for fs-extra ensure functions; Added test coverage for new and updated fs-extra APIs; Added tests for emptyDir and emptyDirSync error propagation; Added tests for ncp copy behavior; Added tests for promise-based API support; Added tests for remove and removeSync operations; Added tests for stat and utimes utilities; Expanded test coverage for fs-extra copy operations; Expanded test coverage for move() and moveSync(); Removed bin/TEST\_file-extra test runner script; Removed synchronous copy test suite.

Dependencies

fs-extra v11.4.1: Modernized dependencies and ESM support

The package has been upgraded to version 11.4.1, requiring Node.js 14.14 or later. This update replaces legacy dependencies like \coffee-script\, \jasmine-node\, and \path-extra\ with modern equivalents: \graceful-fs\ (^4.2.0), \jsonfile\ (^6.0.1), and \universalify\ (^2.0.0). It also introduces explicit ESM support via \exports\ fields pointing to \./lib/esm.mjs\, updates the main entry point to \./lib/index.js\, and refreshes dev dependencies including Mocha (^10.1.0) and Standard (^17.0.0).

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 63 → 64 (+1.3)
  • Rubric changed (rubric-2026.09.12 → rubric-2026.09.18) — scores are not directly comparable.

Lenses

  • Code Health 65 → 65 (+0.0)
  • Architecture 69 → 69 (+0.0)
  • Maturity 59 → 59 (+0.0)
  • Readiness 61 → 62 (+1.0)
  • Security 92 → 96 (+4.1)
  • Performance 100 (new)

Resolved (4)

  • Documentation: no installation or build instructions
  • Documentation: no usage examples (docs/ensureDir.md)
  • Medium: security finding (details withheld)
  • Medium: security finding (details withheld)

New (1)

  • No assertions: should pass readdir errors to the callback (lib/empty/tests/empty-dir.test.js)

Changes since last survey

  • 6 commits — 5 feature/other, 1 fixes

By area

  • (root) — 2 commits
  • .github/workflows — 1 commit
  • docs/fs-read-write-writev.md — 1 commit
  • lib/empty — 1 commit
  • lib/move — 1 commit

Notable commits

  • fix: fix: propagate emptyDir directory read errors (#1080)
  • change: 11.4.1
  • change: Remove broken link (#1083)
  • change: Remove obsolete docs note
  • change: Treat Unicode-normalization-only renames like case-only renames (#1079)
  • change: Update GH Actions versions (#1082)

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

jprichardson/node-fs-extra was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 2 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 1e223d3b1e26b7ebef7f402acf0e3b5533cc5833 — the exact code this score is about.
  • Scored under rubric-2026.09.18 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-e569280dd5e2.