nodejs / nodejs/userland-migrations

Spec: Rimraf to Native `fs.rm()` Comparison Suite

Open
#472 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

good first issue human let's do it
Dominant language
TypeScript
Stars
85
Forks
55
Avg merge
3d 11h
Merged PRs (30d)
9

Description

Description

We should document and codemod the migration from rimraf v3/v4/v5 to node:fs.rm() in Node.js v24.

  • The migration should be divided by rimraf v3, v4, and v5.
  • The migration should separate import replacement from runtime behavior differences.
  • The migration should call out observed output gaps so version-specific behavior is explicit.
  • The migration should keep the deletion wiring and example structure aligned across all baselines.
  • The migration should include compensating patterns for code that depends on legacy glob handling or retry behavior.

Important points

  • rimraf v3 and v4 expose the older package-style recursive delete APIs, while v5 uses named exports.
  • rimraf glob patterns do not map directly to fs.rm(), but they can be migrated with fs.globSync() plus fs.rm() or fs.rmSync().
  • Most cases are a straight source-import migration, but a few cases need behavior notes because glob handling or missing-path behavior differs at runtime.
  • The codemod should prefer built-in node:fs imports for Node.js-only code.
  • fs.rmdir({ recursive: true }) is deprecated and should not be used as a replacement.

Examples

rimraf v3 -> node:fs v24
- import rimraf from "rimraf-v3";
+ import { globSync, rmSync } from "node:fs";
+ import { rm as rmPromise } from "node:fs/promises";

Literal recursive delete:

- rimraf("dist", (error) => {
-   if (error) throw error;
- });
+ await rmPromise("dist", {
+   recursive: true,
+   force: true,
+ });

Observed runtime behavior:

--- rimraf v3
+++ node:fs v24
@@
 (no changes)

Example of glob migration:

- rimraf("dist/**/*.js", (error) => {
-   if (error) throw error;
- });
+ for (const filePath of globSync("dist/**/*.js")) {
+   rmSync(filePath, { recursive: true, force: true });
+ }
rimraf v4 -> node:fs v24
- import rimraf from "rimraf-v4";
+ import { globSync, rmSync } from "node:fs";
+ import { rm as rmPromise } from "node:fs/promises";

Observed runtime behavior:

--- rimraf v4
+++ node:fs v24
@@
 (no changes)

Example of the same migration pattern with no compensation needed:

- await rimraf("dist", {
-   glob: false,
- });
+ await rmPromise("dist", {
+   recursive: true,
+   force: true,
+ });
rimraf v5 -> node:fs v24
- import { rimraf, rimrafSync } from "rimraf-v5";
+ import { globSync, rmSync } from "node:fs";
+ import { rm as rmPromise } from "node:fs/promises";

Observed runtime behavior:

--- rimraf v5
+++ node:fs v24
@@
 (no changes)

Example of sync migration:

- rimrafSync("dist");
+ rmSync("dist", {
+   recursive: true,
+   force: true,
+ });

Caveats

  • These are migration differences, not stream-style output gaps.
  • The version split matters when code depends on glob expansion, missing-path behavior, or Windows retry handling.
  • If the code relies on package-specific retry semantics, keep the behavior explicit instead of assuming parity with native deletion.
  • If the code only needs literal recursive deletion, prefer the Node core behavior and remove the rimraf dependency.
  • If the code depends on glob expansion, keep the globbing step separate and use fs.globSync() before deletion.

Refs

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked Node.js fs.rm(), fs.globSync(), and fs.rmdir() documentation and the rimraf README. Compare the v3, v4, and v5 examples for imports, glob handling, missing paths, and retry behavior; done means the comparison suite, codemod guidance, and compensating patterns cover each stated baseline.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.