CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-npmcli--arborist

Comprehensive node_modules tree management library for npm dependency resolution and reification

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

tree-navigation.mddocs/

Dependency Tree Navigation

The Node class represents packages in the dependency tree, providing methods for navigation, querying, and tree manipulation. Each node corresponds to a package folder and maintains relationships with parent, children, and dependency edges.

Capabilities

Constructor

Creates a new Node instance representing a package in the tree.

/**
 * Create a new Node instance
 * @param options - Node configuration options
 */
constructor(options?: NodeOptions): Node;

interface NodeOptions {
  /** Absolute path to package */
  path?: string;
  /** Parent node in tree */
  parent?: Node;
  /** Package name */
  name?: string;
  /** Root node reference */
  root?: Node;
  /** Real filesystem path */
  realpath?: string;
  /** Child node configurations */
  children?: object;
  /** Is development dependency */
  dev?: boolean;
  /** Is optional dependency */
  optional?: boolean;
  /** Is peer dependency */
  peer?: boolean;
  /** Is extraneous package */
  extraneous?: boolean;
  /** Is global package */
  global?: boolean;
  /** Error object if parsing failed */
  error?: Error;
}

Identity and Location Properties

Core properties that identify and locate the node in the filesystem and tree.

interface NodeIdentity {
  /** Package name */
  name: string;
  /** Package name from package.json */
  packageName: string;
  /** Package version */
  version: string;
  /** Filesystem path */
  path: string;
  /** Real filesystem path */
  realpath: string;
  /** Relative location from root */
  location: string;
  /** Unique package identifier */
  pkgid: string;
}

Tree Structure Properties

Properties defining the node's position and relationships in the tree hierarchy.

interface NodeTreeStructure {
  /** Parent node */
  parent: Node | null;
  /** Root node of tree */
  root: Node;
  /** Child nodes by name */
  children: Map<string, Node>;
  /** Filesystem children */
  fsChildren: Set<Node>;
  /** Top-level ancestor */
  top: Node;
  /** Is root node */
  isRoot: boolean;
  /** Is top-level dependency */
  isTop: boolean;
  /** Depth in tree */
  depth: number;
}

Usage Example:

// Navigate tree structure
console.log(`Node: ${node.name}@${node.version}`);
console.log(`Parent: ${node.parent?.name || 'none'}`);
console.log(`Children: ${Array.from(node.children.keys()).join(', ')}`);
console.log(`Depth: ${node.depth}`);

Package Information Properties

Properties containing package metadata and content information.

interface NodePackageInfo {
  /** Contents of package.json */
  package: object;
  /** Resolved URL or path */
  resolved: string;
  /** Package integrity hash */
  integrity: string;
  /** Parsing errors */
  errors: Error[];
}

Dependency Information Properties

Properties describing the node's dependency relationships and flags.

interface NodeDependencyInfo {
  /** Outgoing dependency edges */
  edgesOut: Map<string, Edge>;
  /** Incoming dependency edges */
  edgesIn: Set<Edge>;
  /** Is development dependency */
  dev: boolean;
  /** Is optional dependency */
  optional: boolean;
  /** Is dev-optional dependency */
  devOptional: boolean;
  /** Is peer dependency */
  peer: boolean;
  /** Is extraneous */
  extraneous: boolean;
  /** Is bundled dependency */
  bundled: boolean;
}

Usage Example:

// Check dependency flags
if (node.dev) {
  console.log('This is a development dependency');
}

if (node.optional) {
  console.log('This is an optional dependency');
}

// Examine dependencies
for (const [name, edge] of node.edgesOut) {
  console.log(`Depends on: ${name}@${edge.spec}`);
}

Dependency Resolution

Resolves dependencies using Node.js module resolution algorithm.

/**
 * Resolve a dependency by name using Node.js resolution algorithm
 * @param name - Dependency name to resolve
 * @returns Resolved node or undefined if not found
 */
resolve(name: string): Node | undefined;

Usage Example:

// Resolve a dependency
const expressNode = node.resolve('express');
if (expressNode) {
  console.log(`Express resolved to: ${expressNode.path}`);
} else {
  console.log('Express not found in resolution path');
}

Tree Navigation

Methods for navigating the tree structure and examining relationships.

/**
 * Generator yielding all ancestors up to root
 * @returns Generator of ancestor nodes
 */
ancestry(): Generator<Node>;

/**
 * Check if this node is a descendant of another node
 * @param node - Potential ancestor node
 * @returns True if this is a descendant of the given node
 */
isDescendantOf(node: Node): boolean;

/**
 * Check if node is located within a node_modules directory
 * @returns True if in node_modules
 */
inNodeModules(): boolean;

Usage Examples:

// Walk up ancestry
for (const ancestor of node.ancestry()) {
  console.log(`Ancestor: ${ancestor.name}`);
}

// Check relationships
if (childNode.isDescendantOf(rootNode)) {
  console.log('Child is descendant of root');
}

// Check location
if (node.inNodeModules()) {
  console.log('Node is in node_modules');
}

Node Comparison and Validation

Methods for comparing nodes and validating dependency satisfaction.

/**
 * Check if this node matches another node (same package and version)
 * @param node - Node to compare against
 * @returns True if nodes match
 */
matches(node: Node): boolean;

/**
 * Check if this node satisfies a dependency request
 * @param requested - Edge representing the dependency request
 * @returns True if this node satisfies the request
 */
satisfies(requested: Edge): boolean;

/**
 * Check if this node can replace another node
 * @param node - Node to potentially replace
 * @param ignorePeers - Ignore peer dependency conflicts
 * @returns True if replacement is valid
 */
canReplace(node: Node, ignorePeers?: boolean): boolean;

/**
 * Check if this node can be replaced by another node
 * @param node - Node that would replace this one
 * @param ignorePeers - Ignore peer dependency conflicts
 * @returns True if replacement is valid
 */
canReplaceWith(node: Node, ignorePeers?: boolean): boolean;

/**
 * Check if this node can be deduplicated
 * @param preferDedupe - Prefer deduplication over newer versions
 * @returns True if node can be deduplicated
 */
canDedupe(preferDedupe?: boolean): boolean;

Usage Examples:

// Compare nodes
if (nodeA.matches(nodeB)) {
  console.log('Nodes are identical');
}

// Check satisfaction
if (node.satisfies(edge)) {
  console.log(`${node.name} satisfies ${edge.name}@${edge.spec}`);
}

// Check replacement possibility
if (newNode.canReplace(oldNode)) {
  console.log('New node can replace old node');
}

Tree Manipulation

Methods for modifying the tree structure by moving and replacing nodes.

/**
 * Replace this node with another node in the tree
 * @param node - Node to replace this one with
 */
replace(node: Node): void;

/**
 * Replace another node with this node
 * @param node - Node to be replaced
 */
replaceWith(node: Node): void;

/**
 * Get the bundling parent for this node
 * @param path - Path for bundling resolution
 * @returns Bundling parent node
 */
getBundler(path?: string[]): Node | null;

Usage Example:

// Replace a node in the tree
if (newVersion.canReplace(oldVersion)) {
  oldVersion.replace(newVersion);
  console.log('Node replaced successfully');
}

Query and Selection

CSS-like selector queries for finding nodes in the tree.

/**
 * Find nodes matching CSS-like selector
 * @param query - CSS-like selector string
 * @param opts - Query options
 * @returns Array of matching nodes
 */
querySelectorAll(query: string, opts?: QueryOptions): Node[];

interface QueryOptions {
  /** Return all matches vs first match */
  all?: boolean;
}

Usage Examples:

// Find all dev dependencies
const devDeps = tree.querySelectorAll('[dev]');

// Find nodes by name
const expressNodes = tree.querySelectorAll('[name="express"]');

// Find nodes with specific attributes
const optionalNodes = tree.querySelectorAll('[optional]');

Information and Debugging

Methods for getting detailed information about the node and its presence in the tree.

/**
 * Explain why this node is present in the tree
 * @param edge - Specific edge to explain
 * @param seen - Array of already seen nodes (for cycle detection)
 * @returns Explanation object
 */
explain(edge?: Edge | null, seen?: Node[]): any;

/**
 * Convert node to JSON representation
 * @returns JSON representation of the node
 */
toJSON(): object;

/**
 * Validate root overrides configuration
 * @throws Error if overrides are invalid
 */
assertRootOverrides(): void;

Usage Example:

// Get explanation for why node exists
const explanation = node.explain();
console.log('Node explanation:', explanation);

// Convert to JSON for inspection
const nodeData = node.toJSON();
console.log('Node data:', JSON.stringify(nodeData, null, 2));

Link Information Properties

Properties specific to identifying and working with symbolic links.

interface NodeLinkInfo {
  /** Is symbolic link (false for regular Node) */
  isLink: boolean;
  /** Link target (self for Node, target for Link) */
  target: Node;
  /** Incoming links */
  linksIn: Set<Link>;
}

Usage Example:

// Check if node is a link
if (node.isLink) {
  console.log(`Link target: ${node.target.path}`);
} else {
  console.log('Regular package node');
}

// Check for incoming links
if (node.linksIn.size > 0) {
  console.log(`Node has ${node.linksIn.size} incoming links`);
}

Install with Tessl CLI

npx tessl i tessl/npm-npmcli--arborist

docs

arborist.md

edges.md

index.md

links.md

shrinkwrap.md

tree-navigation.md

tile.json