CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-find-up

Find a file or directory by walking up parent directories

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

find-up

Find a file or directory by walking up parent directories. This library provides a comprehensive set of functions for traversing filesystem hierarchies upward from a starting directory to locate files or directories by name, pattern, or custom matcher function.

Package Information

  • Package Name: find-up
  • Package Type: npm
  • Language: JavaScript/TypeScript (ESM)
  • Installation: npm install find-up

Core Imports

import { 
  findUp, 
  findUpSync, 
  findUpMultiple, 
  findUpMultipleSync, 
  findUpStop, 
  pathExists, 
  pathExistsSync, 
  type Match, 
  type Options 
} from "find-up";

For specific imports:

import { findUp } from "find-up";
import { pathExists } from "find-up";

Basic Usage

import path from 'node:path';
import { findUp, pathExists } from 'find-up';

// Find a single file by name
console.log(await findUp('package.json'));
//=> '/Users/sindresorhus/project/package.json'

// Find from multiple possible names
console.log(await findUp(['config.json', 'config.js']));
//=> '/Users/sindresorhus/project/config.js'

// Find using a custom matcher function
console.log(await findUp(async directory => {
  const hasPackageJson = await pathExists(path.join(directory, 'package.json'));
  return hasPackageJson && directory;
}, {type: 'directory'}));
//=> '/Users/sindresorhus/project'

Architecture

find-up is built around a simple but powerful directory traversal pattern with several key architectural components:

  • Traversal Engine: Core upward directory walking algorithm that starts from a given directory and moves up the filesystem hierarchy
  • Matcher System: Flexible matching system supporting both simple string/array patterns and custom matcher functions
  • Async/Sync Variants: Parallel implementations for both asynchronous and synchronous operations across all functions
  • Multiple Results: Support for both single-result (findUp) and multiple-result (findUpMultiple) search patterns
  • Search Control: Fine-grained control over search behavior with findUpStop symbol and configurable stopping points
  • Path Utilities: Integration with path-exists library for robust filesystem existence checking
  • Type Safety: Complete TypeScript integration with proper type inference and overload patterns

The library follows a consistent API pattern where each core function has both async and sync variants, and each supports both simple name-based matching and custom matcher function approaches.

Capabilities

Single File Finding

Find the first occurrence of a file or directory by walking up parent directories.

/**
 * Find a file or directory by walking up parent directories (async)
 * @param name - Name or array of names to search for
 * @param options - Search configuration options
 * @returns Promise resolving to the first path found or undefined
 */
function findUp(name: string | readonly string[], options?: Options): Promise<string | undefined>;

/**
 * Find a file or directory using a custom matcher function (async)
 * @param matcher - Function called for each directory in the search
 * @param options - Search configuration options
 * @returns Promise resolving to the first path found or undefined
 */
function findUp(matcher: (directory: string) => (Match | Promise<Match>), options?: Options): Promise<string | undefined>;

/**
 * Find a file or directory by walking up parent directories (sync)
 * @param name - Name or array of names to search for
 * @param options - Search configuration options
 * @returns The first path found or undefined
 */
function findUpSync(name: string | readonly string[], options?: Options): string | undefined;

/**
 * Find a file or directory using a custom matcher function (sync)
 * @param matcher - Function called for each directory in the search
 * @param options - Search configuration options
 * @returns The first path found or undefined
 */
function findUpSync(matcher: (directory: string) => Match, options?: Options): string | undefined;

Multiple File Finding

Find all occurrences of a file or directory by walking up parent directories.

/**
 * Find files or directories by walking up parent directories (async)
 * @param name - Name or array of names to search for
 * @param options - Search configuration options
 * @returns Promise resolving to array of all paths found
 */
function findUpMultiple(name: string | readonly string[], options?: Options): Promise<string[]>;

/**
 * Find files or directories using a custom matcher function (async)
 * @param matcher - Function called for each directory in the search
 * @param options - Search configuration options
 * @returns Promise resolving to array of all paths found
 */
function findUpMultiple(matcher: (directory: string) => (Match | Promise<Match>), options?: Options): Promise<string[]>;

/**
 * Find files or directories by walking up parent directories (sync)
 * @param name - Name or array of names to search for
 * @param options - Search configuration options
 * @returns Array of all paths found
 */
function findUpMultipleSync(name: string | readonly string[], options?: Options): string[];

/**
 * Find files or directories using a custom matcher function (sync)
 * @param matcher - Function called for each directory in the search
 * @param options - Search configuration options
 * @returns Array of all paths found
 */
function findUpMultipleSync(matcher: (directory: string) => Match, options?: Options): string[];

Path Existence Checking

Utility functions for checking if files or directories exist.

/**
 * Check if a path exists (async)
 * @param path - Path to check for existence
 * @returns Promise resolving to true if path exists, false otherwise
 */
function pathExists(path: string): Promise<boolean>;

/**
 * Check if a path exists (sync)
 * @param path - Path to check for existence
 * @returns True if path exists, false otherwise
 */
function pathExistsSync(path: string): boolean;

Search Control

Symbol for controlling search behavior in matcher functions.

/**
 * Symbol that can be returned by a matcher function to stop the search
 * and force findUp to immediately return undefined
 */
const findUpStop: unique symbol;

Types

/**
 * Possible return values from matcher functions
 */
type Match = string | typeof findUpStop | undefined;

/**
 * Base options from locate-path library
 */
interface LocatePathOptions {
  /** Directory to start the search from (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 chosen path type (default: true) */
  readonly allowSymlinks?: boolean;
}

/**
 * Configuration options for find-up functions (extends locate-path options)
 */
type Options = {
  /** Directory path where the search halts if no matches are found (default: root directory) */
  readonly stopAt?: string;
} & LocatePathOptions;

Usage Examples

Finding Configuration Files

import { findUp } from 'find-up';

// Find the nearest package.json
const packagePath = await findUp('package.json');
console.log(packagePath);
//=> '/Users/sindresorhus/project/package.json'

// Find any of several config file types
const configPath = await findUp(['.eslintrc.js', '.eslintrc.json', '.eslintrc.yml']);
console.log(configPath);
//=> '/Users/sindresorhus/project/.eslintrc.json'

Using Custom Matcher Functions

import path from 'node:path';
import { findUp, pathExists, findUpStop } from 'find-up';

// Find a directory containing both package.json and src/
const projectRoot = await findUp(async directory => {
  const hasPackage = await pathExists(path.join(directory, 'package.json'));
  const hasSrc = await pathExists(path.join(directory, 'src'));
  return hasPackage && hasSrc ? directory : undefined;
}, { type: 'directory' });

// Stop search early for performance
const workspacePath = await findUp(directory => {
  return path.basename(directory) === 'work' ? findUpStop : 'workspace.json';
});

Finding Multiple Instances

import { findUpMultiple } from 'find-up';

// Find all package.json files up the directory tree
const allPackageFiles = await findUpMultiple('package.json');
console.log(allPackageFiles);
//=> [
//     '/Users/sindresorhus/project/packages/cli/package.json',
//     '/Users/sindresorhus/project/package.json'
//   ]

Synchronous Operations

import { findUpSync, pathExistsSync } from 'find-up';

// Synchronous file finding
const configPath = findUpSync('config.json');

// Synchronous path checking
const exists = pathExistsSync('/path/to/file.txt');

Advanced Configuration

import { findUp } from 'find-up';

// Start search from specific directory
const result = await findUp('target.txt', {
  cwd: '/Users/sindresorhus/deep/nested/path'
});

// Look for directories instead of files
const dirResult = await findUp('node_modules', {
  type: 'directory'
});

// Stop search at specific directory
const limitedResult = await findUp('file.txt', {
  stopAt: '/Users/sindresorhus'
});

// Disable symlink following
const noSymlinksResult = await findUp('file.txt', {
  allowSymlinks: false
});

Common Patterns

Project Root Detection

import { findUp } from 'find-up';

// Find project root by looking for common project indicators
const projectRoot = await findUp([
  'package.json',
  'cargo.toml', 
  'go.mod',
  '.git'
], { type: 'directory' });

Configuration Loading

import path from 'node:path';
import { findUp, pathExists } from 'find-up';

// Find and load the nearest configuration file
const configPath = await findUp(async directory => {
  const candidates = [
    path.join(directory, 'my-tool.config.js'),
    path.join(directory, 'my-tool.config.json'),
    path.join(directory, '.my-toolrc')
  ];
  
  for (const candidate of candidates) {
    if (await pathExists(candidate)) {
      return candidate;
    }
  }
  
  return undefined;
});

Performance Optimization

import { findUp, findUpStop } from 'find-up';

// Stop search early to avoid traversing the entire filesystem
const result = await findUp(directory => {
  // Stop if we've reached a system directory
  if (directory === '/usr' || directory === '/opt') {
    return findUpStop;
  }
  
  // Continue searching for our target
  return 'my-file.txt';
});

docs

index.md

tile.json