This is the graph library responsible for representing the packages that are involved in a given install.
Overview · Concepts · Architecture · API · Usage · Related Workspaces · References
Overview
The @vltpkg/graph workspace models a project’s dependency
relationships and drives npm-compatible installs by computing how
node_modules should be structured. It exposes a public API through
src/index.ts that re-exports core types and workflows.
At a glance:
Graphencapsulates the full dependency graph for a project (including monorepo workspaces), and is the source of truth for how to lay outnode_modules.Noderepresents a unique package instance (uniqueness provided by@vltpkg/dep-id).Edgerepresents a dependency relationship from a dependent to a dependency (eg.dependencies,devDependencies,peerDependencies, etc.).Diffdescribes the minimal set of changes required to transform an Actual graph (disk) into an Ideal graph (desired outcome), which is then applied by thereifysubsystem.
Concepts
- Importers: Root-level nodes used as starting points of the graph.
The
mainImporteris the project root (itspackage.json), and the remaining importers are workspaces discovered by@vltpkg/workspaces. - Hidden Lockfile: A performance optimization stored at
node_modules/.vlt-lock.jsonmirroring the current on-disk state to accelerate subsequent loads of the Actual graph. - Modifiers: Configuration for selectively altering dependency
resolution via DSS queries in
vlt.json. - Peer Contexts: Isolation mechanism for peer dependencies that allows multiple versions of the same package when peer requirements differ.
API
actual.load(options): Graph
Recursively loads the node_modules folder found at projectRoot in
order to create a graph representation of the current installed
packages.
ideal.build(options): Promise<Graph>
Builds the ideal dependency graph by loading from lockfile (preferred)
or actual graph, then expanding dependencies by fetching manifests.
Requires packageInfo and remover in addition to standard options.
lockfile.load(options): Graph
Loads the lockfile file found at projectRoot and returns the graph.
lockfile.save(options): void
Saves the graph to vlt-lock.json.
reify(options): Promise<ReifyResult>
Computes a Diff between the Actual and Ideal graphs and applies the
minimal filesystem changes (creating/deleting links, writing
lockfiles, hoisting, lifecycle scripts) to make the on-disk install
match the Ideal graph. Returns { diff, buildQueue }.
install(options, add?): Promise<{ graph, diff, buildQueue }>
High-level install orchestration that handles graph building, reify,
and lockfile management. Supports --frozen-lockfile,
--clean-install, and --lockfile-only modes.
mermaidOutput(graph): string
Generates Mermaid flowchart syntax from graph data.
humanReadableOutput(graph, options): string
Generates ASCII tree output with optional colors. Used in vlt ls.
jsonOutput(graph): JSONOutputItem[]
Returns array of {name, fromID, spec, type, to, overridden} items.
Usage
High-Level Install
import { install } from '@vltpkg/graph'
const { graph, diff, buildQueue } = await install({ projectRoot: process.cwd(), packageInfo, packageJson, scurry, allowScripts: '*',})Load Actual Graph and Reify
import { actual, ideal, reify } from '@vltpkg/graph'import { RollbackRemove } from '@vltpkg/rollback-remove'
const remover = new RollbackRemove()
// Load current on-disk stateconst from = actual.load({ projectRoot: process.cwd(), packageJson, scurry, loadManifests: true,})
// Build intended end state (may start from lockfile or actual)const to = await ideal.build({ projectRoot: process.cwd(), packageInfo, packageJson, scurry, remover,})
// Apply minimal changes to match Idealconst { diff, buildQueue } = await reify({ graph: to, actual: from, packageInfo, packageJson, scurry, remover, allowScripts: '*',})Working With Lockfiles
import { lockfile } from '@vltpkg/graph'
// Load virtual graph from vlt-lock.jsonconst graph = lockfile.load({ projectRoot, mainManifest, packageJson,})
// Save to vlt-lock.jsonlockfile.save({ graph })Graph Visualization
import { mermaidOutput, humanReadableOutput, jsonOutput,} from '@vltpkg/graph'
// Mermaid flowchart (for docs, dashboards)const mermaid = mermaidOutput({ edges: [...graph.edges], nodes: [...graph.nodes.values()], importers: graph.importers,})
// ASCII tree with colors (used in `vlt ls`)const tree = humanReadableOutput( { edges: [...graph.edges], nodes: [...graph.nodes.values()], importers: graph.importers, }, { colors: true },)
// JSON array of dependency itemsconst json = jsonOutput({ edges: [...graph.edges], nodes: [...graph.nodes.values()], importers: graph.importers,})Architecture
Graph construction modes supported by the library:
-
Virtual Graphs (lockfile-based)
- Load and save via
src/lockfile/load.tsandsrc/lockfile/save.ts - Hidden lockfile:
node_modules/.vlt-lock.jsonfor faster loads - 📖 Lockfile README
- Load and save via
-
Actual Graphs (filesystem-based)
- Loaded by traversing
node_modulesviasrc/actual/load.ts - May shortcut to Hidden Lockfile if present and valid
- File layout changes are performed by
src/reify/
- Loaded by traversing
-
Ideal Graphs (desired end state)
- Entry:
src/ideal/build.ts - Starts from Virtual (preferred) or falls back to Actual
- Merges
add/removeinput with importer manifests usingsrc/ideal/get-importer-specs.ts - Fetches and expands manifests using
@vltpkg/package-info, reuses existing nodes that satisfy specs - 📖 Ideal README
- Entry:
Finally, src/diff.ts computes changes and src/reify/ applies them
to the filesystem.
Related Workspaces
@vltpkg/dep-id: Unique IDs for packages, ensuringNodeidentity@vltpkg/spec: Parse/normalize dependency specifiers and registry semantics@vltpkg/semver: Semantic version parsing/comparison@vltpkg/satisfies: Check if a DepID satisfies a Spec@vltpkg/package-info: Fetch remote manifests and artifacts (registry, git, tarball)@vltpkg/package-json: Read and cache localpackage.jsonfiles@vltpkg/workspaces: Monorepo workspace discovery and grouping@vltpkg/rollback-remove: Safe file removal with rollback capability@vltpkg/vlt-json: Loadvlt.jsonconfiguration (modifiers, etc.)
References
- package.json format and behavior: https://docs.npmjs.com/cli/v11/configuring-npm/package-json
- Semantic Versioning: https://semver.org/spec/v2.0.0.html
- Monorepos: https://monorepo.tools