npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

esfinder

v0.0.2-alpha.7

Published

A fast and lightweight tool for analyzing module dependencies and finding which files depend on a given module.

Downloads

110

Readme

esfinder

npm version npm downloads bundle JSDocs License

English | 简体中文

A fast and powerful tool for analyzing module dependencies and finding related files in JavaScript and TypeScript projects. ESFinder supports multiple parsers (Babel, SWC, OXC) and provides comprehensive dependency analysis capabilities.

✨ Features

  • 🚀 Multiple Parsers: Support for Babel, SWC, and OXC parsers
  • High Performance: Optimized with caching and efficient algorithms
  • 🔍 Comprehensive Analysis: Find related files, circular dependencies, unused exports
  • 📦 Smart Resolution: Automatic file extension resolution and path handling
  • 🛠️ Developer Friendly: Rich API with TypeScript support
  • 🎯 Zero Config: Works out of the box with sensible defaults

📦 Installation

npm install esfinder

🚀 Quick Start

import { getRelatedFiles, parseExports } from 'esfinder'

// Parse file exports
const exports = await parseExports('./src/utils.ts')
console.log('Exports:', Array.from(exports))

// Find related files
const relatedFiles = await getRelatedFiles(['./src/utils.ts'], './src/components')
console.log('Related files:', relatedFiles)

🎯 Parser Options

ESFinder supports three different parsers, each optimized for different use cases:

Babel Parser (Default)

import { parseExports } from 'esfinder'
  • Best for: Production analysis, complex syntax support
  • Pros: Most complete feature set, excellent accuracy
  • Cons: Slower performance, higher memory usage

SWC Parser

import { parseExports } from 'esfinder/swc'
  • Best for: Development environments, balanced performance
  • Pros: Fast parsing, good syntax support
  • Cons: Limited plugin ecosystem

OXC Parser

import { parseExports } from 'esfinder/oxc'
  • Best for: Large projects, CI/CD environments
  • Pros: Fastest performance, lowest memory usage
  • Cons: Basic feature set, limited syntax support

Benchmark

➜  esfinder git:(main) ✗ node benchmark/compare-parsers.mjs
🚀 ESFinder Parser Performance Benchmark

📁 Test file: /Users/olive/Desktop/code/Sunny-117/esfinder/test/fixtures/source.ts
🔄 Iterations: 1000

📊 Babel Parser:
  ⏱️  Time: 192.92ms
  📈 Avg: 0.193ms per file

📊 SWC Parser:
  ⏱️  Time: 49.28ms
  📈 Avg: 0.049ms per file
  🚀 Speedup: 3.9x faster than Babel

📊 OXC Parser:
  ⏱️  Time: 28.79ms
  📈 Avg: 0.029ms per file
  🚀 Speedup: 6.7x faster than Babel
  🚀 Speedup: 1.7x faster than SWC

💾 Cache Effectiveness Test:
  🔥 First parse: 1.66ms
  ⚡ Cached parse: 0.04ms
  🚀 Cache speedup: 38x faster
  📊 Cache entries: 1

✨ Benchmark completed!

📚 Core API

Basic Functions

parseExports(filePath: string): Promise<Set<string>>

Parse all exports from a file.

const exports = await parseExports('./src/utils.ts')
// Returns: Set { 'formatDate', 'parseUrl', 'default' }

parseImports(filePath: string): Promise<Set<string>>

Parse all imports from a file.

const imports = await parseImports('./src/app.ts')
// Returns: Set { '/path/to/utils.ts', '/path/to/config.ts' }

getRelatedFiles(files: string[], importsDir: string, extensions?: string[]): Promise<string[]>

Find files that import from the specified files.

const relatedFiles = await getRelatedFiles(
  ['./src/utils.ts'],
  './src/components',
  ['.ts', '.tsx'] // optional
)

Advanced Functions

buildDependencyGraph(projectDir: string): Promise<Map<string, {imports: Set<string>, exports: Set<string>}>>

Build a complete dependency graph for the project.

const graph = await buildDependencyGraph('./src')
for (const [file, { imports, exports }] of graph) {
  console.log(`${file} imports ${imports.size} files, exports ${exports.size} items`)
}

findCircularDependencies(projectDir: string): Promise<string[][]>

Detect circular dependencies in your project.

const cycles = await findCircularDependencies('./src')
cycles.forEach((cycle) => {
  console.log('Circular dependency:', cycle.join(' → '))
})

getAllDependencies(filePath: string): Promise<Set<string>>

Get all dependencies of a file recursively.

const allDeps = await getAllDependencies('./src/app.ts')
console.log('All dependencies:', Array.from(allDeps))

getReverseDependencies(targetFile: string, projectDir: string): Promise<string[]>

Find all files that depend on the target file.

const reverseDeps = await getReverseDependencies('./src/utils.ts', './src')
console.log('Files depending on utils.ts:', reverseDeps)

findUnusedExports(projectDir: string): Promise<Map<string, Set<string>>>

Find unused exports in your project.

const unusedExports = await findUnusedExports('./src')
for (const [file, unused] of unusedExports) {
  console.log(`${file} has unused exports:`, Array.from(unused))
}

🛠️ Utility Functions

Cache Management

import { clearCache, getCacheStats } from 'esfinder'

// Get cache statistics
const stats = getCacheStats()
console.log('Cache stats:', stats)

// Clear all caches
clearCache()

Path Resolution

import { DEFAULT_EXTENSIONS, resolveImportPath } from 'esfinder'

const resolved = resolveImportPath('./utils', '/src/components', DEFAULT_EXTENSIONS)

📖 Usage Examples

Test File Discovery

Find which test files need to run when source files change:

import { getRelatedFiles, parseExports } from 'esfinder'

async function findTestsToRun(changedFiles: string[]) {
  // Pre-cache exports
  await Promise.all(changedFiles.map(file => parseExports(file)))

  // Find related test files
  const testFiles = await getRelatedFiles(changedFiles, './src/__tests__')
  return testFiles
}

Project Health Check

Analyze your project for potential issues:

import { findCircularDependencies, findUnusedExports } from 'esfinder'

async function healthCheck(projectDir: string) {
  const [cycles, unusedExports] = await Promise.all([
    findCircularDependencies(projectDir),
    findUnusedExports(projectDir)
  ])

  console.log(`Found ${cycles.length} circular dependencies`)
  console.log(`Found ${unusedExports.size} files with unused exports`)
}

Refactoring Impact Analysis

Understand the impact of code changes:

import { getAllDependencies, getReverseDependencies } from 'esfinder'

async function analyzeRefactorImpact(targetFile: string, projectDir: string) {
  const [affectedFiles, dependencies] = await Promise.all([
    getReverseDependencies(targetFile, projectDir),
    getAllDependencies(targetFile)
  ])

  return { affectedFiles, dependencies: Array.from(dependencies) }
}

⚡ Performance Tips

  1. Choose the right parser for your use case
  2. Use caching effectively - ESFinder automatically caches results
  3. Batch operations instead of processing files individually
  4. Limit scope by specifying file extensions
  5. Monitor cache usage in long-running processes

📊 Performance Comparison

| Parser | Speed | Memory | Features | Best For | |--------|-------|--------|----------|----------| | Babel | Slow | High | Complete | Production | | SWC | Fast | Medium | Good | Development | | OXC | Fastest | Low | Basic | CI/CD |

🔧 Configuration

ESFinder works with zero configuration, but you can customize:

// Custom file extensions
const relatedFiles = await getRelatedFiles(
  files,
  searchDir,
  ['.vue', '.svelte', '.ts'] // custom extensions
)

// Custom project structure
const graph = await buildDependencyGraph('./src', ['.ts', '.tsx'])

🖥️ CLI Usage

ESFinder comes with a powerful CLI tool:

# Install globally
npm install -g esfinder

# Parse exports from a file
esfinder exports src/utils.ts

# Find related files
esfinder related src/utils.ts src/config.ts --dir src/components

# Run project health check
esfinder check ./src

# Build dependency graph
esfinder graph ./src

# Manage cache
esfinder cache --stats
esfinder cache --clear

📚 Documentation

🤝 Contributing

We welcome contributions! Please see our Contributing Guidelines and Code of Conduct.

Development Setup

# Clone the repository
git clone https://github.com/Sunny-117/esfinder.git

# Install dependencies
pnpm install

# Run tests
pnpm test

# Build the project
pnpm build

📄 License

MIT License © Sunny-117