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 Edge class represents dependency relationships between packages in the tree. Edges automatically update to point to the appropriate target when the tree structure changes, providing validation and error reporting for dependency resolution.
Creates a new Edge representing a dependency relationship.
/**
* Create a new dependency edge
* @param options - Edge configuration options
*/
constructor(options: EdgeOptions): Edge;
interface EdgeOptions {
/** Edge type */
type: 'prod' | 'dev' | 'optional' | 'peer' | 'peerOptional' | 'workspace';
/** Dependency name */
name: string;
/** Version specifier */
spec: string;
/** Source node that has the dependency */
from: Node;
/** Accept range (optional) */
accept?: string;
/** Override configuration (optional) */
overrides?: object;
}Usage Example:
const { Edge } = require('@npmcli/arborist');
// Create a production dependency edge
const edge = new Edge({
type: 'prod',
name: 'express',
spec: '^4.18.0',
from: rootNode
});Static properties available on the Edge class.
interface EdgeStatics {
/** Array of valid edge types */
static types: ['prod', 'dev', 'optional', 'peer', 'peerOptional', 'workspace'];
/** Array of possible error types */
static errors: ['DETACHED', 'MISSING', 'PEER LOCAL', 'INVALID'];
}Core properties that identify and describe the dependency relationship.
interface EdgeBasicInfo {
/** Dependency name */
name: string;
/** Edge type */
type: 'prod' | 'dev' | 'optional' | 'peer' | 'peerOptional' | 'workspace';
/** Version specifier (may be overridden) */
spec: string;
/** Original version specifier */
rawSpec: string;
/** Accept range */
accept: string;
/** Source node that has the dependency */
from: Node;
/** Target node that satisfies the dependency */
to: Node | null;
}Usage Example:
// Examine edge properties
console.log(`Dependency: ${edge.name}@${edge.spec}`);
console.log(`Type: ${edge.type}`);
console.log(`From: ${edge.from.name}`);
console.log(`To: ${edge.to?.name || 'unresolved'}`);Boolean properties indicating the specific type of dependency.
interface EdgeTypeFlags {
/** Is production dependency */
prod: boolean;
/** Is development dependency */
dev: boolean;
/** Is optional dependency */
optional: boolean;
/** Is peer dependency */
peer: boolean;
/** Is workspace dependency */
workspace: boolean;
/** Is bundled dependency */
bundled: boolean;
}Usage Example:
// Check dependency type
if (edge.prod) {
console.log('Production dependency');
} else if (edge.dev) {
console.log('Development dependency');
} else if (edge.optional) {
console.log('Optional dependency');
} else if (edge.peer) {
console.log('Peer dependency');
}Properties indicating the validation state and any errors with the dependency.
interface EdgeValidation {
/** Is edge valid (target satisfies spec) */
valid: boolean;
/** Error type if invalid, null if valid */
error: string | null;
/** Target is missing */
missing: boolean;
/** Target doesn't satisfy spec */
invalid: boolean;
/** Peer dependency found locally (invalid) */
peerLocal: boolean;
/** Has peer dependency conflicts */
peerConflicted: boolean;
}Usage Examples:
// Check validation status
if (edge.valid) {
console.log('Dependency is satisfied');
} else {
console.log(`Dependency error: ${edge.error}`);
if (edge.missing) {
console.log('Target package is missing');
} else if (edge.invalid) {
console.log('Target package version does not satisfy spec');
} else if (edge.peerLocal) {
console.log('Peer dependency found in local node_modules (invalid)');
}
}
// Handle different error types
switch (edge.error) {
case 'MISSING':
console.log('Package needs to be installed');
break;
case 'INVALID':
console.log('Package version is incompatible');
break;
case 'PEER LOCAL':
console.log('Peer dependency incorrectly installed locally');
break;
case 'DETACHED':
console.log('Edge has been detached from tree');
break;
}Properties related to dependency overrides and resolution modifications.
interface EdgeOverrides {
/** Override configuration */
overrides: object | null;
}Methods for testing whether a node satisfies this dependency edge.
/**
* Test if a node satisfies this dependency edge
* @param node - Node to test for satisfaction
* @returns True if the node satisfies this edge
*/
satisfiedBy(node: Node): boolean;Usage Example:
// Test if a node satisfies the dependency
const candidateNode = tree.resolve(edge.name);
if (candidateNode && edge.satisfiedBy(candidateNode)) {
console.log(`${candidateNode.name}@${candidateNode.version} satisfies ${edge.spec}`);
} else {
console.log('Candidate node does not satisfy dependency');
}Methods for managing edge state and resolution.
/**
* Reload edge resolution, optionally forcing a hard reload
* @param hard - Force complete re-resolution
*/
reload(hard?: boolean): void;
/**
* Detach edge from the tree (marks as DETACHED)
*/
detach(): void;Usage Examples:
// Reload edge resolution after tree changes
edge.reload();
// Force complete re-resolution
edge.reload(true);
// Detach edge when removing dependency
edge.detach();Methods for getting detailed information about the edge and its resolution.
/**
* Explain the edge relationship and resolution
* @param seen - Array of already seen edges (for cycle detection)
* @returns Explanation object
*/
explain(seen?: Edge[]): any;
/**
* Convert edge to JSON representation
* @returns JSON representation of the edge
*/
toJSON(): object;Usage Example:
// Get detailed explanation of edge
const explanation = edge.explain();
console.log('Edge explanation:', explanation);
// Convert to JSON for inspection
const edgeData = edge.toJSON();
console.log('Edge data:', JSON.stringify(edgeData, null, 2));prod)Regular runtime dependencies required for the package to function.
const prodEdge = new Edge({
type: 'prod',
name: 'express',
spec: '^4.18.0',
from: rootNode
});dev)Dependencies only needed during development, testing, or building.
const devEdge = new Edge({
type: 'dev',
name: 'jest',
spec: '^29.0.0',
from: rootNode
});optional)Dependencies that are optional and won't cause installation to fail if unavailable.
const optionalEdge = new Edge({
type: 'optional',
name: 'fsevents',
spec: '^2.3.0',
from: rootNode
});peer)Dependencies that should be provided by the consuming application.
const peerEdge = new Edge({
type: 'peer',
name: 'react',
spec: '>=16.8.0',
from: componentNode
});peerOptional)Peer dependencies that are optional and won't cause warnings if missing.
const peerOptionalEdge = new Edge({
type: 'peerOptional',
name: 'typescript',
spec: '>=4.0.0',
from: libNode
});workspace)Dependencies between packages in a monorepo workspace.
const workspaceEdge = new Edge({
type: 'workspace',
name: 'shared-utils',
spec: '*',
from: appNode
});The dependency target cannot be found in the tree.
if (edge.error === 'MISSING') {
console.log(`${edge.name} needs to be installed`);
}The dependency target exists but doesn't satisfy the version specification.
if (edge.error === 'INVALID') {
console.log(`${edge.name}@${edge.to.version} doesn't satisfy ${edge.spec}`);
}A peer dependency was found in the local node_modules, which violates the peer contract.
if (edge.error === 'PEER LOCAL') {
console.log(`Peer dependency ${edge.name} should not be installed locally`);
}The edge has been detached from its source node, typically during tree modifications.
if (edge.error === 'DETACHED') {
console.log(`Edge ${edge.name} has been detached from tree`);
}Install with Tessl CLI
npx tessl i tessl/npm-npmcli--arborist