Promisified Node Which
which-promise is a JavaScript utility library that provides a Promise-based API for locating executable programs within a user's system `PATH` environment variable. It functions as a direct, promisified wrapper around the robust and widely used `node-which` library, offering a modern, asynchronous interface to a fundamental system operation. The package is currently at version 1.0.0, indicating a stable and mature API that is unlikely to see frequent breaking changes. As a wrapper, its release cadence is closely tied to updates and bug fixes in its underlying dependency, `node-which`, primarily focusing on stability and compatibility across different Node.js versions and operating systems. Its primary differentiator is simplifying the asynchronous lookup of executables by leveraging native JavaScript Promises, making it straightforward to integrate into contemporary `async/await` workflows, which is a significant improvement over traditional callback-based approaches. It is particularly valuable in Node.js development for scripting, tooling, and applications that require programmatic discovery of system binaries.
Common errors
-
Error: not found: [command-name]
cause The specified command-name executable could not be found within any directories listed in the system's PATH environment variable, or it lacks execution permissions.fixVerify that the command-name is correctly spelled and that its containing directory is included in your system's PATH. On Linux/macOS, check file permissions with `ls -l $(which command-name)`. You can also provide a custom `path` option to `whichPromise(cmd, { path: '/custom/bin' })`. -
TypeError: whichPromise is not a function
cause This typically occurs when attempting to use ES Module `import` syntax (e.g., `import whichPromise from 'which-promise';` or `import { whichPromise } from 'which-promise';`) with a CommonJS-only package, or incorrectly requiring the module.fixEnsure you are using the correct CommonJS `require` syntax: `const whichPromise = require('which-promise');`. If in an ESM module, consider dynamic import (`import('which-promise').then(m => m)`) or `createRequire`. -
Error [ERR_REQUIRE_ESM]: require() of ES Module ... from ... not supported.
cause While less common for `which-promise` itself (which is CJS), this error indicates you are trying to `require()` an ES Module in a CommonJS context. If `node-which` or any transitive dependency *becomes* ESM-only, this could manifest.fixEnsure all dependencies are compatible with your module system. If `which-promise` or `node-which` ever transitions to ESM-only, you would need to adjust your project to use ESM `import` statements or dynamic `import()` where appropriate.
Warnings
- gotcha The `which-promise` package is a CommonJS (CJS) module. Attempting to use the `import` statement directly in an ES Module (ESM) context without a bundler (like Webpack or Rollup) or Node.js's specific CJS-ESM interop settings (e.g., `"type": "module"` in package.json with `createRequire`) may lead to errors like 'whichPromise is not a function' or 'ERR_REQUIRE_ESM'.
- gotcha The behavior of `which-promise` (and its underlying `node-which` dependency) is heavily influenced by the `PATH` environment variable. If `PATH` is incorrectly configured or does not include the directory where an executable resides, `which-promise` will correctly report that the command was not found, even if it exists elsewhere on the system.
- gotcha Since `which-promise` is a wrapper around `node-which`, its functionality and any subtle behaviors (e.g., Windows executable extension handling, permissions checks) are inherited from `node-which`. Changes or nuances in `node-which` behavior will directly affect `which-promise`.
- deprecated For newer Node.js applications, consider using `util.promisify(require('which'))` directly. This approach might reduce dependency count if `which-promise` is the only external wrapper used for `which`, leveraging native Node.js Promise utility.
Install
-
npm install which-promise -
yarn add which-promise -
pnpm add which-promise
Imports
- whichPromise
import whichPromise from 'which-promise';
const whichPromise = require('which-promise'); - whichPromise
import { whichPromise } from 'which-promise';const whichPromise = require('which-promise'); - WhichPromiseFunction
import type { whichPromise } from 'which-promise';// No specific type import needed for basic usage, but for TypeScript: import whichPromise = require('which-promise');
Quickstart
const whichPromise = require('which-promise');
async function findExecutables() {
try {
// Find the 'node' executable in the system's PATH
const nodePath = await whichPromise('node');
console.log(`Node.js executable found at: ${nodePath}`);
// Find the 'npm' executable
const npmPath = await whichPromise('npm');
console.log(`npm executable found at: ${npmPath}`);
// Example of a command that might not exist
const nonExistentCommand = 'nonexistent-tool-123';
await whichPromise(nonExistentCommand);
console.log(`This line will not be reached if '${nonExistentCommand}' is not found.`);
} catch (err) {
if (err.message.startsWith('not found')) {
console.error(`Error: ${err.message}`);
} else {
console.error(`An unexpected error occurred: ${err.message}`);
}
}
}
findExecutables();