Skip to content

Graph Modifiers

Graph Modifiers are a recent addition to the vlt client that allow you to dynamically alter and refine how the package dependency graph is traversed and evaluated. This feature gives you granular control over installed packages, including their transitive dependencies, letting you target exactly which parts of the graph to operate on.


Overview

Graph Modifiers extend the existing dependency graph traversal logic in vlt using our Dependency Selector Syntax. These selectors let you modify the behavior of an existing vlt install operation, allowing you to target specific packages and their dependencies.

Note: In its initial release, Graph Modifiers support a limited subset of the Dependency Selector Syntax:

  • :root
  • :project
  • :workspace
  • ID selectors (#package-name)
  • Semantic version selectors (:v(^1.0.0))
  • Direct dependency combinator (>)

Understanding how Graph Modifiers work

User-defined Graph Modifier entries will be read and applied during the graph build phase. In order to apply new modifier entries the graph build will be retriggered every time the "modifiers" property is changed in the vlt.json file


Usage

Graph Modifiers are configured via the modifiers field in your vlt.json configuration file. Below are some examples on how to use it:

Basic Overrides

{
"modifiers": {
":root > #express": "^4.18.0",
"#lodash": "^4.17.21"
}
}

The keys are selectors that identify which dependency to override, and the values specify the versions to enforce.

Universal Selector

{
"modifiers": {
"#react": "^18.2.0"
}
}

Replaces every occurrence of react in the dependency tree with version ^18.2.0.

Path-Specific Selector

{
"modifiers": {
":root > #next > #react": "^17.0.0"
}
}

Only overrides react when it’s a direct dependency of next, which is a direct dependency of the root project.

Adding Comments to Selectors

{
"modifiers": {
"/* pin down exact version */ :root > #express > #body-parser > #qs": "=6.10.0"
}
}

Inline comments can be added to selector keys for clarity.

Specificity Resolution

{
"dependencies": {
"express": "^4.17.0"
},
"modifiers": {
":root > #express > #cookie": "^0.5.0",
"#cookie": "^0.4.0"
}
}

CSS-like specificity rules determine which modifier applies when multiple selectors match the same dependency. Here, the more specific :root > #express > #cookie takes precedence over #cookie.

Semver Pseudo-Selectors

{
"modifiers": {
"#lodash:v(^4.0.0)": "^4.17.21"
}
}

This only affects lodash dependencies matching the semver range ^4.0.0.

Integration with Catalogs

{
"catalogs": {
"tools": {
"react": "^18.2.0"
}
},
"modifiers": {
"#react": "catalog:tools"
}
}

It’s possible to point to configured catalogued versions from modifiers.

Using with workspaces

{
"workspaces": "packages/*",
"modifiers": {
":workspace > #typescript": "^5.0.0",
"#core:workspace > #typescript": "~5.1.0"
}
}

You may use the :workspace selector to target workspaces. In the example above we target a specific workspace named core by combining the #core ID selector with the :workspace selector.


Best Practices

  • Start Small: Test modifiers incrementally to understand how you are modifying your install,
  • Combine wisely: Use path-specific and universal selectors to control installations accurately.

See Also


Graph Modifiers enable precise and efficient package management in vlt. Future updates will expand selector support and add advanced capabilities.