Changesets
Releases run through changesets. Add one in the same commit as the change it describes:
npm run changeset # describe the change, pick a bump
npm run version-packages # apply pending changesets, write CHANGELOGs
npm run release # build, then publish
release builds first because the .d.ts files are generated output — they
have to exist before packing, or the published packages ship without types.
Two release groups
The ten runtime and adapter packages are a fixed group: one version across
all of them, always released together. A consumer cannot end up with
@pdsjs/node built against a different @pdsjs/core than it expects, which is
the failure mode a repo full of independently-versioned packages invites.
Internal workspace:* ranges resolve to that exact version at pack time.
@pdsjs/spaces versions on its own, and must stay out of the fixed group.
Inside it, every release escalated to a major regardless of what the
changesets asked for — a minor and a patch shipped as 2.0.0 with no
### Major Changes in any changelog. Measured from a 2.0.0 baseline with a
single core: minor changeset:
| fixed group | result |
|---|---|
| all eleven packages | 3.0.0 |
| spaces excluded | 2.1.0 |
| no fixed group | 2.1.0 |
@pdsjs/cloudflare depends on spaces and cannot defer the import — the Durable
Object constructor is synchronous — so a spaces bump still propagates to the
whole group. That is one major per upstream change to
proposal 0016,
which is the price of the coupling; it is not a reason to put spaces back in the
group and pay a major on every release instead. The lever on the remaining
propagation is that cloudflare import, not the release config.
npm run version-packages refuses to continue if the version moves further
than any changeset asked for, because this failure was otherwise invisible
until after publishing.
@pdsjs/account-ui is a private devDependency
@pdsjs/account-ui (the built account-page bundle) is imported by both
@pdsjs/node (dynamically) and @pdsjs/cloudflare (statically, for the
synchronous Durable Object constructor), and both are in the fixed group. It is
private (never published) and declared a devDependency of both, on
purpose — do not change either.
- Private, because it is an internal build input: the fixed-group packages
inline it at build time and nobody installs it standalone. Being private keeps
it out of changeset versioning entirely (
privatePackages.version: false), so it needs no changeset and has no npm version to reconcile. - devDependency, not
dependencies/peerDependencies, for two reasons. First, a published package must not carry a private (unpublished) package in its runtime deps, or consumers cannot install it — a devDependency is not installed by consumers, so this is fine. Second, declaring it a runtime or even an optional peer dependency escalated every account-ui change into a whole-group major:workspace:*pins the exact version, so any bump read as out-of-range and the fixed group carried the escalation with a version number ahead of its changelog.
Because it is decoupled, an account-ui change does not auto-bump the fixed
group. To ship a UI change, add a changeset for the fixed group (e.g.
@pdsjs/core patch) so those packages republish with the rebuilt bundle.
Private packages (the examples) are neither versioned nor published.
