pnpm Workspaces and Catalogs

A pnpm 69,400 workspace is declared in pnpm-workspace.yaml, not package.json. The same file can hold a catalog naming one version range for each shared dependency, so a monorepo's packages cannot drift onto different Express 24,430 versions. Here is Yarn Workspaces's BookNest monorepo rebuilt for pnpm.

pnpm-workspace.yaml with a default catalogYAML
packages:
  - "packages/*"
catalog:
  express: ^5.1.0
  pg: ^8.16.3

packages/api/package.json then declares "@booknest/catalog": "workspace:^", "express": "catalog:" and "pg": "catalog:"; packages/catalog is the one-function library from before.

Installing the workspace and running every package's testsShell
cd ~/v5-ch1/pnpm-ws
pnpm install
pnpm -r test
Output
Scope: all 3 workspace projects
...
Progress: resolved 80, reused 80, downloaded 0, added 80, done
Done in 133ms using pnpm v12.6.0
Scope: 2 of 3 workspace projects
$ node -e "console.log(require('.').formatPrice(24))"
$24.00
$ node -e "console.log(require('@booknest/catalog').formatPrice(18.5))"
$18.50

pnpm -r (recursive) runs a script in every package in dependency order, so the catalog library ran first; --filter @booknest/api narrows it to one package. pnpm-lock.yaml gains a catalogs: section recording each range and the version it resolved to (Express 5.2.1, pg 8.23.0), and upgrading Express everywhere is a one-line change. Named catalogs, used as catalog:legacy, let a monorepo keep two sanctioned versions during a migration. pnpm introduced the catalog: protocol; Bun 73,307 (Bun Workspaces) and Yarn 4.10 11,798 and later (in .yarnrc.yml) now accept it too, while npm 2,036 has no equivalent.