Recursive File and Directory Remover
premove is a lightweight, cross-platform utility for Node.js that recursively removes files and directories, functioning as a programmatic `rm -rf`. It offers both `Promise`-based asynchronous (`premove`) and synchronous (`premove/sync`) APIs. The current stable version is 4.0.0. Releases are generally infrequent but address breaking changes or add features, as seen with v3.0.0's migration to named exports and v4.0.0's consistent boolean return for non-existent paths. Key differentiators include its tiny footprint (208B-260B), explicit support for both async/await and synchronous operations, and a built-in CLI. It's an alternative to `fs.rm` (or `fs.rmdir` with `recursive` option), providing a simpler, focused API for recursive deletion with safeguards against deleting critical system paths.
Common errors
-
TypeError: premove is not a function
cause Attempting to call `premove` after importing it as a default export (e.g., `import premove from 'premove'`) when it should be a named export.fixChange your import statement to `import { premove } from 'premove';` (ESM) or `const { premove } = require('premove');` (CommonJS). -
Property 'then' does not exist on type 'boolean'. Did you mean the instance member 'trim'?
cause Trying to use `.then()` or `await` on the result of `premove` from the `premove/sync` submodule, which returns a synchronous boolean, not a Promise.fixIf you need `Promise`-based behavior, import `premove` from the main package (`'premove'`). If you intend synchronous behavior, simply use the boolean return value directly without `await` or `.then()`.
Warnings
- breaking The `premove` utility migrated from a default export to a named export. This affects both ESM `import` statements and CommonJS `require()` calls.
- breaking The `premove` (async) function now consistently returns a `Promise<boolean>`, even if the path does not exist. Previously, it would synchronously return `false` if the path was not found. The `premove/sync` version always returns `boolean`.
- gotcha The `premove` CLI and underlying utility by default refuse to delete critical system paths such as the OS home directory (`os.homedir`), the system root (`/` or `C:\`), or items not contained within the `--cwd` path for safety.
- gotcha For synchronous operations, you must explicitly import `premove` from `'premove/sync'`. The default import (`'premove'`) is always asynchronous and Promise-based.
Install
-
npm install premove -
yarn add premove -
pnpm add premove
Imports
- premove
import premove from 'premove'
import { premove } from 'premove' - premove (sync)
import premove from 'premove/sync'
import { premove } from 'premove/sync' - premove (CJS)
const premove = require('premove')const { premove } = require('premove')
Quickstart
import { premove } from 'premove';
import { resolve, join } from 'path';
import { mkdir, writeFile } from 'fs/promises';
async function runExample() {
const baseDir = resolve(__dirname, 'temp_premove_test');
const targetDir = join(baseDir, 'foo', 'bar');
const targetFile = join(baseDir, 'hello.txt');
try {
// Setup: Create directories and a file for deletion
await mkdir(targetDir, { recursive: true });
await writeFile(targetFile, 'temporary content');
console.log(`Created test directory: ${targetDir}`);
console.log(`Created test file: ${targetFile}`);
// Example 1: Remove a directory recursively
let removedFoo = await premove(join(baseDir, 'foo'));
console.log(`'${join(baseDir, 'foo')}' existed and was removed: ${removedFoo}`);
// Example 2: Remove a file using cwd option
let removedFile = await premove('hello.txt', { cwd: baseDir });
console.log(`'hello.txt' in '${baseDir}' existed and was removed: ${removedFile}`);
// Example 3: Attempt to remove a non-existent path
let removedNonExistent = await premove(join(baseDir, 'non-existent-path'));
console.log(`'non-existent-path' existed and was removed: ${removedNonExistent} (expected false)`);
} catch (err) {
console.error('Error during premove example:', err);
} finally {
// Clean up if baseDir still exists (e.g., if an error occurred early)
try {
const { premove: premoveSync } = await import('premove/sync');
premoveSync(baseDir);
console.log(`Cleaned up base directory: ${baseDir}`);
} catch (cleanupErr) {
console.warn('Failed to clean up base directory:', cleanupErr.message);
}
}
}
runExample();