{"id":11580,"library":"premove","title":"Recursive File and Directory Remover","description":"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.","status":"active","version":"4.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/lukeed/premove","tags":["javascript","del","remove","rimraf","typescript"],"install":[{"cmd":"npm install premove","lang":"bash","label":"npm"},{"cmd":"yarn add premove","lang":"bash","label":"yarn"},{"cmd":"pnpm add premove","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Since v3.0.0, `premove` is a named export for both ESM and CommonJS. The default export was removed.","wrong":"import premove from 'premove'","symbol":"premove","correct":"import { premove } from 'premove'"},{"note":"To use the synchronous version, you must import from the 'premove/sync' submodule. It's also a named export.","wrong":"import premove from 'premove/sync'","symbol":"premove (sync)","correct":"import { premove } from 'premove/sync'"},{"note":"For CommonJS, use destructuring assignment to access the named export since v3.0.0.","wrong":"const premove = require('premove')","symbol":"premove (CJS)","correct":"const { premove } = require('premove')"}],"quickstart":{"code":"import { premove } from 'premove';\nimport { resolve, join } from 'path';\nimport { mkdir, writeFile } from 'fs/promises';\n\nasync function runExample() {\n  const baseDir = resolve(__dirname, 'temp_premove_test');\n  const targetDir = join(baseDir, 'foo', 'bar');\n  const targetFile = join(baseDir, 'hello.txt');\n\n  try {\n    // Setup: Create directories and a file for deletion\n    await mkdir(targetDir, { recursive: true });\n    await writeFile(targetFile, 'temporary content');\n    console.log(`Created test directory: ${targetDir}`);\n    console.log(`Created test file: ${targetFile}`);\n\n    // Example 1: Remove a directory recursively\n    let removedFoo = await premove(join(baseDir, 'foo'));\n    console.log(`'${join(baseDir, 'foo')}' existed and was removed: ${removedFoo}`);\n\n    // Example 2: Remove a file using cwd option\n    let removedFile = await premove('hello.txt', { cwd: baseDir });\n    console.log(`'hello.txt' in '${baseDir}' existed and was removed: ${removedFile}`);\n\n    // Example 3: Attempt to remove a non-existent path\n    let removedNonExistent = await premove(join(baseDir, 'non-existent-path'));\n    console.log(`'non-existent-path' existed and was removed: ${removedNonExistent} (expected false)`);\n\n  } catch (err) {\n    console.error('Error during premove example:', err);\n  } finally {\n    // Clean up if baseDir still exists (e.g., if an error occurred early)\n    try {\n      const { premove: premoveSync } = await import('premove/sync');\n      premoveSync(baseDir);\n      console.log(`Cleaned up base directory: ${baseDir}`);\n    } catch (cleanupErr) {\n      console.warn('Failed to clean up base directory:', cleanupErr.message);\n    }\n  }\n}\n\nrunExample();","lang":"typescript","description":"Demonstrates asynchronous recursive deletion of files and directories using `premove`, including the `cwd` option, and shows the boolean return value for existing and non-existing paths. Also includes cleanup using the sync version."},"warnings":[{"fix":"Update your import/require statements: `import { premove } from 'premove'` or `const { premove } = require('premove')`.","message":"The `premove` utility migrated from a default export to a named export. This affects both ESM `import` statements and CommonJS `require()` calls.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Ensure your async code correctly `await`s the result of `premove` and expects a `Promise<boolean>`.","message":"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`.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Always specify target paths relative to a safe `cwd` or ensure they are within intended deletion scope. Do not attempt to use `premove` for deleting system-level directories like `/` directly.","message":"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.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"Use `import { premove } from 'premove/sync'` or `const { premove } = require('premove/sync')` for synchronous usage.","message":"For synchronous operations, you must explicitly import `premove` from `'premove/sync'`. The default import (`'premove'`) is always asynchronous and Promise-based.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Change your import statement to `import { premove } from 'premove';` (ESM) or `const { premove } = require('premove');` (CommonJS).","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.","error":"TypeError: premove is not a function"},{"fix":"If 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()`.","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.","error":"Property 'then' does not exist on type 'boolean'. Did you mean the instance member 'trim'?"}],"ecosystem":"npm"}