Skip to content

fix(packaging): mark entry-specific peers optional so subpath consumers are not forced to install them - #26

Merged
KruGoL merged 1 commit into
mainfrom
fix/optional-peer-deps
Aug 5, 2026
Merged

fix(packaging): mark entry-specific peers optional so subpath consumers are not forced to install them#26
KruGoL merged 1 commit into
mainfrom
fix/optional-peer-deps

Conversation

@KruGoL

@KruGoL KruGoL commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Problem

sphere-quest-frontend CI fails on npm ci:

npm error `npm ci` can only install packages when your package.json and package-lock.json are in sync.
npm error Missing: @dnd-kit/core@6.3.1 from lock file
npm error Missing: @dnd-kit/sortable@10.0.0 from lock file
npm error Missing: @dnd-kit/utilities@3.2.2 from lock file
npm error Missing: @tanstack/react-table@8.21.3 from lock file
npm error Missing: @dnd-kit/accessibility@3.1.1 from lock file
npm error Missing: @tanstack/table-core@8.21.3 from lock file

Mechanism

npm 7+ auto-installs non-optional peerDependencies. Everything listed there is therefore expected in every consumer's lockfile, whether or not that consumer imports the entry point that needs it. The lockfile in question was generated on a machine with legacy-peer-deps=true set globally, which skips peer auto-install; CI has no such setting, so npm ci finds the tree out of sync and refuses.

That app imports only @unicitylabs/sphere-ui/announcements — the subpath added in 0.1.39, whose bundle imports nothing but react, lucide-react, react-markdown and remark-gfm. Forcing it to declare a data-table and a drag-and-drop stack it never loads would defeat the purpose of that subpath existing.

Fix

Move the entry-specific peers into peerDependenciesMeta as optional: true, following the precedent this library already sets for recharts (needed only by ./analytics):

Package Needed by
@tanstack/react-table root barrel (DataTable)
@dnd-kit/core, @dnd-kit/sortable root barrel and ./hooks
@dnd-kit/utilities root barrel (MediaGallery)
@tanstack/react-query nothing — see below

The peerDependencies entries themselves are unchanged, so the supported version ranges are still declared; only the auto-install obligation is dropped. react and react-dom stay required.

@tanstack/react-query

Included, because it is not merely entry-specific — no entry point imports it at all. git grep react-query matches only package.json, the tsup external list and the README; zero source files. It was nevertheless being installed into every consumer. The verification below shows npm pulling @tanstack/react-query@5.101.4 and @tanstack/query-core into a consumer that wants neither. It did not appear in the reported error only because sphere-quest-frontend happens to declare react-query as a direct dependency itself.

I left the peerDependencies entry in place rather than deleting it, so the ^5 range still documents what to pair with these components if an app uses both.

Verification

Not just a green build here — a green build proves nothing about a consumer's install. npm packed this branch and installed the tarball into a throwaway consumer whose package.json lists only the tarball, react and react-dom. Control = published 0.1.39 from the registry, identical steps.

Control (published 0.1.39)npm install --legacy-peer-deps=false drags in 8 unwanted packages:

node_modules/@dnd-kit  -> accessibility, core, sortable, utilities
node_modules/@tanstack -> query-core, react-query, react-table, table-core

and with the lockfile generated the way the dev machine does it (--legacy-peer-deps=true), npm ci --dry-run --legacy-peer-deps=false reproduces the reported CI failure exactly:

npm error code EUSAGE
npm error Missing: @dnd-kit/core@6.3.1 from lock file
npm error Missing: @dnd-kit/sortable@10.0.0 from lock file
npm error Missing: @dnd-kit/utilities@3.2.2 from lock file
npm error Missing: @tanstack/react-query@5.101.4 from lock file
npm error Missing: @tanstack/react-table@8.21.3 from lock file
npm error Missing: @dnd-kit/accessibility@3.1.1 from lock file
npm error Missing: @tanstack/query-core@5.101.4 from lock file
npm error Missing: @tanstack/table-core@8.21.3 from lock file

This branch — same consumer, same commands:

  • npm install --legacy-peer-deps=false → exit 0
  • npm ci --dry-run --legacy-peer-deps=false → exit 0
  • node_modules/@dnd-kit → absent, node_modules/@tanstack → absent, recharts → absent
  • installed tree nodes in the lockfile matching @dnd-kit/@tanstack0 (the only textual mentions are this package's own peerDependencies/peerDependenciesMeta metadata, which npm always mirrors into the lockfile)
  • import('@unicitylabs/sphere-ui/announcements') resolves and returns all 11 exports with none of the optional peers installed

And the actual failing CI scenario — lockfile built with --legacy-peer-deps=true, then npm ci --dry-run --legacy-peer-deps=false — now exits 0.

npm run test:run (168 tests, 23 files), npm run typecheck and npm run build all pass. npm run lint is broken in this repo (eslint not installed, no config) — pre-existing, untouched.

Impact on root-barrel consumers

sphere, sphere-dev-portal and sphere-backoffice import from the package root, which genuinely needs the table and dnd packages. Checked each package.json: all three already declare all four as their own direct dependencies, so dropping the auto-install changes nothing for them.

Repo @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities @tanstack/react-table
sphere ^6.3.1 ^10.0.0 ^3.2.2 ^8.21.3
sphere-dev-portal ^6.3.1 ^8.0.0 ^3.2.2 ^8.17.3
sphere-backoffice ^6.3.1 ^10.0.0 ^3.2.2 ^8.17.3

The trade-off is real but already paid for: an app that uses the root barrel without declaring these now gets a build error instead of a silent auto-install. None of the three is in that position.

Notes

  • No version bump, no tag, no publish — release is the manual workflow_dispatch. version is left at 0.1.39.
  • sphere-quest-frontend is untouched; its lockfile gets regenerated once this is published.
  • The README "Peer Dependencies" section now records which entry point needs each peer and why they must not be made required again, so this doesn't get "fixed" back. That section was also stale (it omitted @dnd-kit/utilities and recharts, listed the wrong sortable range, and listed lucide-react as a peer when it is a regular dependency).

…ot forced to install them

npm 7+ auto-installs non-optional peerDependencies, so every package listed
there ends up in each consumer's lockfile whether or not the consumer imports
the entry point that needs it. A consumer that only uses the ./announcements
subpath (react + lucide-react + react-markdown + remark-gfm) was still being
handed the data-table and drag-and-drop stack, and its `npm ci` failed in CI
with "Missing: @dnd-kit/core@6.3.1 from lock file" (and five more) whenever the
lockfile had been generated on a machine with legacy-peer-deps=true, which
skips peer auto-install.

Move @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities, @tanstack/react-table
and @tanstack/react-query into peerDependenciesMeta as optional, following the
precedent already set for recharts (./analytics only). The peerDependencies
entries stay, so the supported version ranges are still declared; only the
auto-install obligation is dropped. react and react-dom remain required.

@tanstack/react-query is included because no entry point imports it at all --
it is not reachable from any bundle, yet it was being installed into every
consumer.

The root-barrel consumers (sphere, sphere-dev-portal, sphere-backoffice) each
already declare all four as their own direct dependencies, so nothing changes
for them.
@KruGoL
KruGoL merged commit 915f2bb into main Aug 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant