npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

package-constraints

v0.1.3

Published

> Enforce rules for dependencies in a package or workspace

Downloads

9

Readme

package-constraints

Enforce rules for dependencies in a package or workspace

Constraints provide the answer to many problems that arise when managing a workspace with a multitude of packages:

  • How do I ensure all packages use consistent versions of a certain dependency?
  • How can I prevent packages A, B and C from depending on dependency X?
  • How can I force packages to put dependency Y in peerDependencies and never in dependencies?

Constraints are written in prolog in a constraints.pl or constraints.pro file.

Warning

Warning: this package is not stable, the CLI API and rules API is subject to change.

Inspiration

This package is heavily inspired on the current constraints implementation in berry, aka "yarn v2". It is not compatible with berry, but that is subject to change.

Installation

yarn add -D package-constraints
# or
npm install -D package-constraints

Usage

We'll assume you use yarn throughout this usage guide. Replace yarn with npx if you're using npm.

yarn constraints check

This command will validate the constraints and log errors and a final result to stderr. If errors are found, the process will exit with a non-zero exit code.

The following options are available:

  • --quiet: don't log errors and final result to stderr
  • --without-exit-code: always exit with code 0 unless an unexpected error occurs, i.e. this will make the command exit "successfully" if constraints are violated but it will exit with a non-zero exit code if the constraints file is missing.
  • --format: Change the output format, the only supported value is tap. If a format is passed, the output of constraints will be sent to stdout instead of stderr.
  • --output-file FILE...: Log output to file(s). Pass the option more than once to output to multiple files. This option will add an initial output to the process, i.e. setting an output file will not change whether the process logs the result via stdout/stderr. The FILE parameter may be prefixed with a format, separated from the file path with a colon :.

Example usage:

yarn constraints check --without-exit-code --output-file tap:/dev/fd/1 \
      | yarn tap-junit -n constraints.xml

To help with debugging your constraints, you can generate the full constraints file using

# to output via stdio, e.g. to pipe to another process
yarn constraints generate
# or to store in a file
yarn constraints generate full-constraints.pl

You can then inspect the resulting prolog, or load it into a prolog engine to run some queries, e.g.

yarn constraints generate full-constraints.pl
swipl -f full-constraints.pl

Rules

The following rules are available, filled with the data from the package.json files in your workspace:

package/1

package(PackageName).

This rule matches all packages in your workspace.

private_package/1

private_package(PackageName).

This rule matches all private packages in your workspace.

root_package/1

root_package(PackageName).

This rule matches the package name of the workspace root. If the workspace root doesn't have a name, as is possible for yarn workspaces, a dummy name will be used instead.

dependency_type/1

dependency_type(peerDependencies).
dependency_type(dependencies).
dependency_type(devDependencies).

This rule can be used to generate all dependency types. There are only three values: dependencies, peerDependencies and devDependencies.

package_location/2

package_location(PackageName, PackageLocation).

This rule gives access to the location of a package, allowing rules to be written based on the folder structure rather than the package name.

package_version/2

package_version(PackageName, Version).

This rule links a workspace package with its version.

package_has_dependency/4

package_has_dependency(PackageName, DependencyName, DependencyVersion, DependencyType).

This rule matches a package with its declared dependencies.

Queries

The constraints engine will look for matches for the following two predicates:

gen_enforced_dependency_range/4

gen_enforced_dependency_range(PackageName, DependencyName, DependencyVersion, DependencyType).

This rule is queried for every workspace package and every dependency type. The generated matches are compared with the actual dependencies listed in the workspace. If a difference is found, a violation will be logged.

Use a DependencyVersion value of null to mark a dependency as not allowed.

gen_invalid_dependency/4

gen_invalid_dependency(PackageName, DependencyName, DependencyType, Reason).

This rule is queried for every workspace package and every dependency type. Every generated match will be logged as violation.

Recipes for constraints

This section contains a couple of recipes for constraints.

Force packages to depend on the workspace version of workspace packages

The following rule requires all dependencies on packages contained in the workspace itself to use the version in the workspace:

gen_enforced_dependency_range(PackageName, DependencyName, DependencyVersion, DependencyType) :-
  package_has_dependency(PackageName, DependencyName, _, DependencyType),
  package_version(DependencyName, DependencyVersion).

Require all peerDependencies to be listed in devDependencies

Peer-dependencies aren't installed automatically, so for local development these need to be installed separately. The following rule enforces all peer dependencies to be listed as dev dependency, ensuring the package is installed by your package manager.

gen_enforced_dependency_range(PackageName, DependencyName, DependencyVersion, devDependencies) :-
  package_has_dependency(PackageName, DependencyName, DependencyVersion, peerDependencies),