package-constraints
TypeScript icon, indicating that this package has built-in type declarations

0.1.3 • Public • Published

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),

Readme

Keywords

none

Package Sidebar

Install

npm i package-constraints

Weekly Downloads

3

Version

0.1.3

License

MIT

Unpacked Size

149 kB

Total Files

124

Last publish

Collaborators

  • bgotink