fix(cli): resolve packages status the way a Build resolves - #361
Merged
Merged
Conversation
`packages status <name>@<version>` read the machine package home and nothing
else, while the loader finds an external package in two places: the
node_modules chain above whoever requires it, and the machine home addressed by
the version that requirer declares. A package installed where the first half
looks — a pnpm workspace's own node_modules, or the global node_modules a
`npm i -g @hypit/hypit` shares with a `npm i -g @hyperframes/engine` — was
reported `Ready false` and exited 1, and `hypit doctor` then loaded the provider
from it on the next line.
Measured on a global install with an empty machine home, before and after:
@hyperframes/engine@0.7.101 Ready false, exit 1
@hyperframes/engine@0.7.101 Ready true, exit 0
Required by .../packages/provider-hyperframes-local
Installation .../lib/node_modules/@hyperframes/engine
Status now locates the Distribution package that declares the specifier and
asks `locateNodePackage` once, from there — one call covering both places
rather than a second opinion beside the loader, which is how the two came to
disagree. The version is still exact: `distributionPackageDeclaring` matches the
declared range byte for byte, so the requirer is found only at the version asked
for, and the resolved manifest's version is compared again afterwards.
A specifier no Distribution package declares now says so, rather than reporting
a bare `Ready false`, and `install` keeps its own path untouched.
Reading only the machine home remains the answer when there is no Distribution
on disk, because then there is no requirer to resolve from.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
hypit packages status <name>@<version>reported on the machine package home only. The loaderfinds an external package in two places — the node_modules chain above whoever requires it, and the
machine home addressed by the version that requirer declares — so a package installed where the
first half looks was reported not ready, and
hypit doctorloaded the provider from it anyway.The case that surfaced it: an agent container that installs
@hypit/hypitand@hyperframes/enginewithnpm i -g. Both land in the same globalnode_modules, the ancestorwalk from
packages/provider-hyperframes-localfinds the engine, Builds work — andpackages statussaidReady falseand exited 1, so the agent concluded the dependency was missing andwent looking for other package names.
The fix
Status now locates the Distribution package that declares the specifier, then makes one
locateNodePackagecall from there. That single call covers both places the loader looks, insteadof this command reimplementing one of them beside it — which is how the two came to disagree.
Version locking is unchanged in kind and checked twice:
distributionPackageDeclaringmatches thedeclared range byte for byte, so a requirer is found only at the exact version asked for, and the
resolved manifest's version is compared to it afterwards.
installkeeps its own path. With no Distribution on disk, reading the machine home is still theanswer, because then there is no requirer to resolve from.
Measured
Global install, empty machine home (the container's layout), before and after the change:
After, in full:
@hyperframes/producer@0.7.101behaves the same. A specifier nothing declares now names thereason instead of a bare not-ready:
left-pad@1.3.0likewise, both exit 1.The status payload gains
declaredBy,installedVersionanddetailas optional fields; theformat stays
hypit.cli-package@1.Checks
npm run check(tsc) clean.npm run check:distribution -- hypit-hypit-0.2.13.tgzexit 0.npm test: two failures, both present on unmodifiedmainand unrelated —packages/video-cli/test/cli.test.ts"provider-free example plans from installed Sourcepackages", and a sibling case asserting empty stderr that a Node 26
module.register()DeprecationWarning breaks.