Get the first path that exists on disk of multiple paths
npx @tessl/cli install tessl/npm-locate-path@7.2.0locate-path is a utility library that efficiently finds the first existing path from a collection of file or directory paths. It provides both asynchronous and synchronous APIs for checking path existence, with configurable options including concurrency control, path type filtering, symlink handling, and working directory specification.
npm install locate-pathimport { locatePath, locatePathSync } from "locate-path";For CommonJS environments (not recommended as this is an ES module):
const { locatePath, locatePathSync } = require("locate-path");import { locatePath, locatePathSync } from "locate-path";
// Async usage - find first existing file
const files = [
'config.json',
'config.yaml', // Only this one exists
'config.toml'
];
const found = await locatePath(files);
console.log(found); // => 'config.yaml'
// Sync usage
const foundSync = locatePathSync(files);
console.log(foundSync); // => 'config.yaml'
// With options - find directories with concurrency control
const dirs = ['node_modules', 'dist', 'src'];
const foundDir = await locatePath(dirs, {
type: 'directory',
concurrency: 2,
cwd: '/path/to/project'
});Asynchronously find the first existing path from multiple candidates with concurrent checking and configurable options.
/**
* Get the first path that exists on disk of multiple paths
* @param paths - The paths to check (can be any iterable of strings)
* @param options - Configuration options
* @returns Promise resolving to first existing path or undefined if none exist
*/
function locatePath(
paths: Iterable<string>,
options?: AsyncOptions
): Promise<string | undefined>;
interface AsyncOptions {
/** Current working directory (default: process.cwd()) */
readonly cwd?: URL | string;
/** Type of path to match: 'file' or 'directory' (default: 'file') */
readonly type?: 'file' | 'directory';
/** Allow symbolic links to match if they point to the requested path type (default: true) */
readonly allowSymlinks?: boolean;
/** Number of concurrently pending promises (default: Infinity, minimum: 1) */
readonly concurrency?: number;
/** Preserve paths order when searching - disable to improve performance (default: true) */
readonly preserveOrder?: boolean;
}Usage Examples:
// Find first existing config file
const configPath = await locatePath([
'app.config.js',
'app.config.json',
'.apprc'
]);
// Find directories only, with limited concurrency
const srcDir = await locatePath(['src', 'lib', 'source'], {
type: 'directory',
concurrency: 1,
cwd: '/project/root'
});
// Disable symlinks and order preservation for performance
const dataFile = await locatePath(['data.json', 'data.yaml'], {
allowSymlinks: false,
preserveOrder: false
});
// Using URL for cwd
const found = await locatePath(['index.js'], {
cwd: new URL('file:///project/path/')
});Synchronously find the first existing path from multiple candidates with configurable options.
/**
* Synchronously get the first path that exists on disk of multiple paths
* @param paths - The paths to check (can be any iterable of strings)
* @param options - Configuration options
* @returns First existing path or undefined if none exist
*/
function locatePathSync(
paths: Iterable<string>,
options?: Options
): string | undefined;
interface Options {
/** Current working directory (default: process.cwd()) */
readonly cwd?: URL | string;
/** Type of path to match: 'file' or 'directory' (default: 'file') */
readonly type?: 'file' | 'directory';
/** Allow symbolic links to match if they point to the requested path type (default: true) */
readonly allowSymlinks?: boolean;
}Usage Examples:
// Basic synchronous usage
const path = locatePathSync(['readme.md', 'README.md', 'readme.txt']);
// Find executable in different locations
const executable = locatePathSync(['./bin/app', '/usr/local/bin/app'], {
type: 'file',
allowSymlinks: true
});
// Check for project root markers
const projectRoot = locatePathSync(['package.json', 'pyproject.toml', 'Cargo.toml'], {
cwd: process.cwd(),
type: 'file'
});Both functions validate the type parameter and throw an Error if an invalid type is specified:
// These will throw: Error: Invalid type specified: <invalid_type>
await locatePath(['file.txt'], { type: 'invalid' }); // throws
locatePathSync(['file.txt'], { type: 123 }); // throwsFile system errors (permission denied, network issues, etc.) are handled gracefully - paths that cannot be accessed are treated as non-existent rather than throwing errors.
cwd option using Node.js path.resolve().cwd parameter accepts URL objects, which are converted to file paths using fileURLToPath().p-locate for concurrent path checking. Higher concurrency can improve performance when checking many paths.preserveOrder: false can improve performance by allowing the first successful check to return immediately.