v1.0 — Stable Release
Track every import. Instantly.
When a file changes, you need to know what else is affected. importree builds the full import dependency tree for any TypeScript or JavaScript entry point — with zero dependencies and zero AST overhead.
Built for CI pipelines, build tools, monorepo task runners, and test selectors.
npm install importree
Copied!
ESM+CJS
Dual module output
Features
Everything you need.
Nothing you don't.
One job, done right. Resolve every import across your entire codebase with a single function call.
Zero Dependencies
Built entirely on Node.js built-ins. No native binaries, no WASM, no transitive dependency tree of its own. Just pure TypeScript.
Fast Scanning
Regex-based import extraction with concurrent async file traversal. No AST parsing overhead — just the specifiers you need, as fast as reading the file.
Path Alias Support
Resolve @/components, ~/utils, or any custom alias.
Longest-prefix matching with automatic extension probing and index file resolution.
Cache Invalidation
Someone edits utils.ts — which test suites, which pages, which
build targets need to re-run? The pre-computed reverse graph answers that instantly
with getAffectedFiles().
Performance
Benchmarks
Compared with excellent tools like madge, dependency-tree, and the TypeScript compiler on a synthetic project with realistic import patterns.
500 files synthetic project
12.7 ms
full dependency tree for 500 files
Concurrent async traversal + resolver cache
661K ops/s
scanImports throughput on typical source files
Regex-based extraction · zero allocation hot path
26.4 ms
full tree build for 1,000 files
~38 ops/s · scales linearly with project size
0 deps
built entirely on Node.js built-ins
No native binaries · no WASM · no AST parsers
Quick Start
Two functions.
That's the whole API.
Build the tree. Query it. Done.
1Build the tree
import { importree } from 'importree'; const tree = await importree('./src/index.ts', { aliases: { '@': './src' }, }); console.log(tree.files); // ['/abs/src/index.ts', '/abs/src/app.ts', ...] console.log(tree.externals); // ['react', 'lodash', 'node:path'] console.log(tree.graph); // { '/abs/src/index.ts': ['/abs/src/app.ts', ...] }
2Find affected files
import { importree, getAffectedFiles } from 'importree'; const tree = await importree('./src/index.ts'); // When utils.ts changes, what needs rebuilding? const affected = getAffectedFiles( tree, './src/utils.ts' ); console.log(affected); // ['/abs/src/app.ts', '/abs/src/index.ts'] // ^ every file that transitively depends on utils.ts
API Reference
The complete API.
Two functions, five output fields — fully typed with JSDoc. Nothing hidden, nothing undocumented.
importree(entry: string, options?: ImportreeOptions): Promise<ImportTree>
Recursively resolves all static imports, dynamic imports,
require() calls, and re-exports starting from the entry file. Returns
the full dependency graph.
getAffectedFiles(tree: ImportTree, changedFile: string): string[]
BFS traversal of the reverse dependency graph. Returns all files that transitively depend on the changed file — sorted, deterministic, and without the changed file itself.
ImportTree
entrypoint : string
Absolute path of the entry file.
files : string[]
Sorted absolute paths of all local files in the dependency tree.
externals : string[]
Sorted unique bare import specifiers — packages like react,
lodash, node:fs.
graph : Record<string, string[]>
Forward adjacency list. Each file maps to its direct local imports.
reverseGraph : Record<string, string[]>
Reverse adjacency list. Each file maps to files that import it. Pre-computed for fast cache invalidation.