Local Package Versions
This is an addendum to the Getting Started guide.
When some of the packages developed in your monorepo are installed as dependencies in other packages developed in your monorepo, syncpack can check that the versions used are valid and consistent.
Target Problem
A Node.js client to communicate with your HTTP API is developed in your repo:
As-is a front-end application which depends on it:
And a plugin which extends it:
The Developers of this project:
- Provide a Web Service which their customers interact with via their Node.js Client and various Plugins.
- The Plugins are developed to be compatible with any version of the Node.js Client in the entire 1.x range, as defined in their
peerDependencies
. Companies around the world depend on this Client and Plugin and there is no reason to impose that all of them must use the same exact version of the Client. - Use the pnpm
workspace:*
protocol to ensure that the local workspace package of the Client is resolved when working locally on the Plugin. - Want exact versions of the Client and its Retry Plugin when running their Dashboard UI in production.
The local
dependency type
The “local” dependencyType
relates to the version
properties of the package.json files from your own packages being developed in your monorepo.
When local
is enabled, syncpack can see that:
- ❌ The UI is not using the latest client developed locally (
1.2.1
). - ✅ The UI is using the latest plugin developed locally (
1.7.1
). - ❌
workspace:*
is not identical to1.2.1
(see below). - ❌
^1.0.0
is not identical to1.2.1
(see below).
Zero Configuration?
As a sensible default, syncpack defines a monorepo-wide exact version policy as a starting point which can be tuned from there. If your project uses exact versions everywhere, and you always want them to be identical, you will not need to define any configuration.
But most projects are not like that, and we will need to use configuration for syncpack to know what our requirements are.
Possible Solutions
Let’s look at workspace:*
under devDependencies
first and decide on a rule for that:
Option 1: Pin local versions to `workspace:*`
Add a Pinned Version Group so that local packages are always installed using workspace:*
when they are used in devDependencies
.
- An optional label can be added to document the rule.
- The dependencies array defines the names of the dependencies we want to target.
- dependencyTypes results in these dependencies only being targeted by this group when they are located in
devDependencies
. - pinVersion states that these dependencies must always use
workspace:*
.
The fix for the Peer Dependency of ^1.0.0
can also be used to fix the use of workspace:*
. Since the current version of 1.2.1
of the Client is satisfied by both of these ranges, a Same Range Version Group can be used.
The versions will be considered a match unless eg. 2.0.0
of the Client is released, or one of its dependents uses a range which does not include its current version.
Option 2: Check that a dependency's semver ranges always match
Add a Same Range Version Group which allows local packages installed in devDependencies
or peerDependencies
to use different semver ranges, as long as they all match the local package version.
- An optional label can be added to document the rule.
- The dependencies array defines the names of the dependencies we want to target.
- dependencyTypes results in these dependencies only being targeted by this group when they are located in
devDependencies
orpeerDependencies
. - The policy of sameRange states that these dependencies are considered valid if every range matches the others.