Skip to content

fix: support npm install-strategy=linked (.store layout) - #596

Open
manzoorwanijk wants to merge 10 commits into
ds300:masterfrom
manzoorwanijk:fix/support-npm-linked-install-strategy
Open

manzoorwanijk wants to merge 10 commits into
ds300:masterfrom
manzoorwanijk:fix/support-npm-linked-install-strategy

Conversation

@manzoorwanijk

@manzoorwanijk manzoorwanijk commented Mar 10, 2026

Copy link
Copy Markdown

Summary

Adds support for npm install-strategy=linked, where transitive and nested packages only exist under node_modules/.store. Creating, updating, appending, rebasing, applying and reversing patches now work for those packages. Regular installs are unaffected, because resolution only runs when the expected path is missing.

Fixes #595

How it works

  • resolvePackagePath.ts finds the store entry (.store/<name>@<version>-<hash>, scoped under .store/@scope/) using the version from the lockfile.
  • Nested specs follow the parent's real path to the sibling links npm creates, so workspace links into the root .store work too.
  • npm aliases are matched by the real package name recorded in the lockfile.
  • Paths the lockfile doesn't list, or versions with more than one store entry, are left unresolved instead of guessed.
  • The resolved path is used for state files, VCS details, fast forward and rebase, and patch paths are remapped before applying.
  • The makePatch temp repo installs with install-strategy=hoisted, since a copied .npmrc would otherwise turn the package into a symlink git can't diff.

Verified end to end with npm 11. CI's npm versions don't support the linked strategy, so coverage here is unit tests.

@manzoorwanijk

Copy link
Copy Markdown
Author

@ds300 any chance of getting this reviewed anytime soon?

@james-pre

Copy link
Copy Markdown

@ds300 LGTM!

@manzoorwanijk

Copy link
Copy Markdown
Author

A gentle reminder about this

Scoped packages live under .store/@scope/, and nested lockfile paths do
not always match the real dependent, so pick the store entry by lockfile
version instead of the first name match. Drop the name-only ancestor
node_modules fallback, which could patch an unrelated copy.
Reading VCS details, the state file and fast-forwarding during a rebase
all used the logical node_modules path, which does not exist for
packages that only live in .store.
Rebase looked up the state file and reversed patches at the logical
node_modules path, so it reported no state for .store-only packages.
The app's .npmrc is copied into the temp repo, so install-strategy=linked
turned the package into a symlink and git could not diff it.
Follow workspace links into the root .store, read versions from the
store entry name so patches to package.json stay resolvable, and refuse
to pick between same-version entries that npm keys by dependency graph.
--create-issue looked up VCS details again at the logical path, which
throws for packages that only live in .store.
Aliased dependencies are stored under their real package name, which the
lockfile records in the entry's name field.
makePatch reads the lockfile entry for the requested path, so resolving
a nested spec that npm hoists elsewhere crashed later. Check that the
package exists before any lookup that assumes it does.
Stripping it changed CLI output and broke the dev-only-patches snapshot.
@manzoorwanijk

Copy link
Copy Markdown
Author

Today I asked Claude Code and Codex to review the changes and they found some issues which I have fixed in the above commits.

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.

Support npm install-strategy=linked (.store directory layout)

2 participants