vlt Graph Modifiers
Published on

Taking Control with Graph Modifiers

Authors

As JavaScript projects grow in complexity, managing dependency versions becomes increasingly challenging. We've all been there: a transitive dependency has a security vulnerability, a specific package version introduces breaking changes, or you need to enforce consistent versions across your entire dependency tree. Today, we're excited to introduce Graph Modifiers โ€“ a powerful new capability that puts you back in control of your dependency graph.

What Are Graph Modifiers?

Graph Modifiers introduce a new foundation in vlt for advanced dependency graph customization. One of the first features built on top of this system is support for dependency "overrides", similar in spirit to npmโ€™s overrides but reimagined for vltโ€™s modern architecture. Think of them as surgical precision tools for your dependency graph - they allow you to replace specific dependency declarations at any level of your dependency graph.

In the vlt client, overrides are a first-class capability. The Graph Modifiers API is built around our powerful Dependency Selector Syntax (DSS), giving you unprecedented control and flexibility.

Common Use Cases

Before diving into the syntax, let's explore some real-world scenarios where Graph Modifiers shine:

  • Security Vulnerability Fixes: Replace a transitive dependency that has known security issues
  • Version Consistency: Enforce a single version of a package across your entire dependency tree
  • Package Upgrades: Force an upgrade of a dependency that's stuck on an older version
  • Locking packages: Lock a transitive dependency to a specific trusted version

The modifiers Configuration

All Graph Modifiers are configured through the "modifiers" key in your vlt.json file. This is your control center for dependency graph customization:

{
  "workspaces": "packages/*",
  "modifiers": {
    ":root > #express": "^4.18.0",
    "#lodash": "^4.17.21",
    ":workspace > #typescript": "~5.0.0"
  }
}

The syntax is intuitive: the key is a selector that identifies which dependency to override, and the value is the version you want to use instead.

Selector Syntax: Precision Targeting

vlt's Dependency Selector Syntax gives you multiple ways to target exactly the dependency you want to modify.

While the full power of DSS is coming soon, this first release of Graph Modifiers supports a streamlined subset: :root, :workspace, :project, ID selectors (e.g: #package-name), semver-based selectors (e.g: :v(^1.0.0)) and the direct dependency combinator (e.g: >).

Universal Selectors

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

This replaces every occurrence of react in your dependency tree with version ^18.2.0.

Path-Specific Selectors

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

This only replaces react when it's a direct dependency of next, which is a direct dependency of your root project.

Workspace Selectors

{
  "modifiers": {
    ":workspace > #typescript": "~5.0.0"
  }
}

This applies to typescript dependencies within any workspace in your monorepo.

Selector comments

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

Using DSS queries makes it possible to add comments inline to the modifier keys.

Advanced Features

Specificity Resolution

When multiple selectors could match the same dependency, vlt uses CSS-like specificity rules to determine which one wins:

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

In this case, the more specific selector (:root > #express > #cookie) takes precedence over the general one (#cookie) for the cookie dependency of the express dependency of our root project. Everywhere else in the same install will default to cookie at version ^0.4.0.

Semver Pseudo-Selectors

Target dependencies based on their version ranges:

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

This only affects lodash dependencies that match the semver range ^4.0.0.

Using with Catalogs

We announced Catalog support last week which allows you to better manage direct dependencies and dependency groups. You can use Graph Modifiers alongside Catalogs to achieve even more control over your dependency graph.

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

This config defines a catalog for a "tools" group that includes a definition for react. Normally, you'd have to explicitely define the catalog: spec in each of your workspaces/usages of react but with Graph Modifiers we can define an ID selector like #react and ALL dependencies (direct and transitive) will now use the asssociative catalog spec (in this case, react at version ^18.2.0).

Getting Started

Ready to take control of your dependency graph? Here's how to get started:

  1. Add a "modifiers" section to your vlt.json:

    {
      "modifiers": {
        "#package-name": "<version>"
      }
    }
    
  2. Run vlt install to apply your modifiers

  3. Verify the changes using vlt ls to see your dependency tree

What's Next?

Graph Modifiers are just the beginning. We're working on several exciting enhancements:

๐Ÿ”ฎ Coming Soon: Graph Node Replacements

Inspired by pnpm's Package Extensions, this feature will allow you to:

  • Add missing peer dependencies
  • Define optional peer dependencies
  • Fix missing dependencies in third-party packages

๐Ÿ“ˆ Expanded DSS Support

We're expanding the subset of Dependency Selector Syntax available for usage in Graph Modifiers with:

  • More powerful pseudo-selectors
  • Attribute-based selection
  • Descendent and sibling combinators

Try It Today

Graph Modifiers are available now in vlt. Whether you're dealing with security vulnerabilities, version conflicts, or just want more control over your dependency tree, these modifiers give you the precision tools you need.

Ready to get started? Check out our documentation or join our Discord community to share your experiences and get help from the team.

Join the waitlist

Curious to learn more about vlt? Join our waitlist and get early access.

Sign up