@vltpkg/graph
v1.0.0-rc.18
Published
A library that helps understanding & expressing what happens on an install
Keywords
Readme
title: '@vltpkg/graph'
@vltpkg/graph
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 state
const 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 Ideal
const { 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.json
const graph = lockfile.load({
projectRoot,
mainManifest,
packageJson,
})
// Save to vlt-lock.json
lockfile.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 items
const 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
