Comprehensive node_modules tree management library for npm dependency resolution and reification
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The main Arborist class provides high-level dependency tree management operations. It manages three types of trees: actual (what's on disk), virtual (from lockfiles), and ideal (desired state).
Creates a new Arborist instance with configuration options.
/**
* Create a new Arborist instance
* @param options - Configuration options
*/
constructor(options?: ArboristOptions): Arborist;
interface ArboristOptions {
/** Project root path, defaults to current directory */
path?: string;
/** Cache directory path, defaults to ~/.npm/_cacache */
cache?: string;
/** Registry URL, defaults to npm registry */
registry?: string;
/** Node.js version, defaults to process.version */
nodeVersion?: string;
/** Enable binary links, default true */
binLinks?: boolean;
/** Dry run mode, default false */
dryRun?: boolean;
/** Format package-lock.json, default true */
formatPackageLock?: boolean;
/** Force operations, default false */
force?: boolean;
/** Global package mode, default false */
global?: boolean;
/** Skip lifecycle scripts, default false */
ignoreScripts?: boolean;
/** Installation strategy: 'hoisted' or 'shallow', default 'hoisted' */
installStrategy?: 'hoisted' | 'shallow';
/** Lockfile version (1, 2, 3, or null for auto) */
lockfileVersion?: 1 | 2 | 3 | null;
/** Only use package-lock.json, default false */
packageLockOnly?: boolean;
/** Custom packument cache instance */
packumentCache?: any;
/** Rebuild bundled packages, default true */
rebuildBundle?: boolean;
/** Registry host replacement */
replaceRegistryHost?: string;
/** Save prefix for versions, default '^' */
savePrefix?: string;
/** Shell for running scripts */
scriptShell?: string;
/** Workspace names filter */
workspaces?: string[];
/** Enable workspaces support, default true */
workspacesEnabled?: boolean;
}Usage Example:
const Arborist = require('@npmcli/arborist');
const arb = new Arborist({
path: '/path/to/project',
registry: 'https://registry.npmjs.org',
dryRun: false,
force: false
});Loads the actual dependency tree from disk by reading node_modules directories.
/**
* Load actual dependency tree from disk
* @param options - Loading options
* @returns Promise resolving to the root node of the actual tree
*/
loadActual(options?: LoadOptions): Promise<Node>;
interface LoadOptions {
/** Filter function to control which nodes are loaded */
filter?: (node: Node, kidName: string) => boolean;
/** Force loading from actual filesystem, ignore cache */
forceActual?: boolean;
}Usage Example:
// Load complete actual tree
const actualTree = await arb.loadActual();
// Load with filtering
const filteredTree = await arb.loadActual({
filter: (node, kidName) => !kidName.startsWith('.')
});Loads the virtual dependency tree from package.json and lockfiles without reading node_modules.
/**
* Load virtual tree from package.json and lockfiles
* @param options - Loading options
* @returns Promise resolving to the root node of the virtual tree
*/
loadVirtual(options?: LoadOptions): Promise<Node>;Usage Example:
// Load virtual tree from lockfile
const virtualTree = await arb.loadVirtual();
// Access the loaded tree
console.log(`Virtual tree root: ${virtualTree.name}@${virtualTree.version}`);Builds the ideal dependency tree based on package.json, lockfiles, and requested changes.
/**
* Build ideal dependency tree incorporating requested changes
* @param options - Build options including packages to add/remove
* @returns Promise that resolves when ideal tree is built
*/
buildIdealTree(options?: BuildOptions): Promise<void>;
interface BuildOptions {
/** Array of package specifiers to add */
add?: string[];
/** Array of package names to remove */
rm?: string[];
/** Update configuration */
update?: boolean | { all?: boolean; names?: string[] };
/** Where to save added packages */
saveType?: 'prod' | 'dev' | 'optional' | 'peer' | 'peerOptional';
/** Add to bundleDependencies list */
saveBundle?: boolean;
/** Prune extraneous packages, default true */
prune?: boolean;
/** Prefer to deduplicate rather than update */
preferDedupe?: boolean;
/** Use npm v2 style nesting */
legacyBundling?: boolean;
}Usage Examples:
// Add production dependencies
await arb.buildIdealTree({
add: ['express@^4.18.0', 'lodash@latest'],
saveType: 'prod'
});
// Remove packages
await arb.buildIdealTree({
rm: ['old-package', 'unused-dep']
});
// Update all packages
await arb.buildIdealTree({
update: { all: true }
});
// Update specific packages
await arb.buildIdealTree({
update: { names: ['express', 'lodash'] }
});Applies the ideal tree to disk, making the actual tree match the ideal tree.
/**
* Apply ideal tree changes to disk
* @param options - Reification options
* @returns Promise that resolves when reification is complete
*/
reify(options?: ReifyOptions): Promise<void>;
interface ReifyOptions {
/** Write lockfile back to disk, default true */
save?: boolean;
/** Dry run mode - don't make actual changes */
dryRun?: boolean;
/** Dependency types to omit during install */
omit?: string[];
/** Dependency types to include during install */
include?: string[];
}Usage Examples:
// Standard reification
await arb.reify();
// Dry run to see what would change
await arb.reify({ dryRun: true });
// Omit dev dependencies
await arb.reify({ omit: ['dev'] });Runs security audit on the dependency tree.
/**
* Run security audit on dependencies
* @param options - Audit options
* @returns Promise resolving to audit report or reification result if fix=true
*/
audit(options?: AuditOptions): Promise<any>;
interface AuditOptions {
/** Automatically fix vulnerabilities */
fix?: boolean;
/** Use package-lock.json instead of building ideal tree */
packageLock?: boolean;
/** Set of nodes to include in audit */
filterSet?: Set<Node>;
}Usage Examples:
// Run audit without fixing
const auditReport = await arb.audit();
// Run audit and automatically fix issues
await arb.audit({ fix: true });Removes duplicate dependencies by consolidating identical packages.
/**
* Remove duplicate dependencies
* @param options - Deduplication options
* @returns Promise that resolves when deduplication is complete
*/
dedupe(options?: DedupeOptions): Promise<void>;
interface DedupeOptions {
/** Dry run mode */
dryRun?: boolean;
/** Save changes to lockfile */
save?: boolean;
}Usage Example:
// Deduplicate all possible packages
await arb.dedupe();Methods for working with npm workspaces in monorepos.
/**
* Get nodes corresponding to specified workspaces
* @param tree - Root tree node
* @param workspaces - Array of workspace names
* @returns Array of workspace nodes
*/
workspaceNodes(tree: Node, workspaces: string[]): Node[];
/**
* Get dependency set for workspaces including all their dependencies
* @param tree - Root tree node
* @param workspaces - Array of workspace names
* @param includeWorkspaceRoot - Include root workspace dependencies
* @returns Set of nodes in workspace dependency tree
*/
workspaceDependencySet(
tree: Node,
workspaces: string[],
includeWorkspaceRoot?: boolean
): Set<Node>;
/**
* Get dependencies excluding workspace-only dependencies
* @param tree - Root tree node
* @returns Set of non-workspace dependencies
*/
excludeWorkspacesDependencySet(tree: Node): Set<Node>;Usage Example:
// Load tree and get workspace nodes
const tree = await arb.loadActual();
const wsNodes = arb.workspaceNodes(tree, ['workspace-a', 'workspace-b']);
// Get all dependencies for specific workspaces
const wsDepSet = arb.workspaceDependencySet(tree, ['workspace-a']);interface ArboristInstance {
/** Configuration options */
options: ArboristOptions;
/** Resolved cache directory path */
cache: string;
/** Resolved project path */
path: string;
/** Last tree diff result */
diff: any | null;
/** Last audit report */
auditReport: any | null;
/** Registry host replacement setting */
replaceRegistryHost: string;
}Install with Tessl CLI
npx tessl i tessl/npm-npmcli--arborist