Skip to content

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

@manzoorwanijk

Description

@manzoorwanijk

Bug report

When npm is configured with install-strategy=linked (an experimental feature in npm), packages are stored in node_modules/.store/<pkg>@<version>-<hash>/node_modules/<pkg>/ and symlinked into consuming packages' node_modules/. patch-package cannot find packages at these paths and fails to apply patches.

Current Behavior

With install-strategy=linked in .npmrc, running patch-package in postinstall fails with:

Error: Patch file found for package lighthouse which is not present at node_modules/@wordpress/e2e-test-utils-playwright/node_modules/lighthouse

The package exists, but at a different path:

node_modules/.store/lighthouse@12.2.2-E1oDY3hhcKvr16czLc4uyw/node_modules/lighthouse/

A symlink exists at the expected nested path, but it points into .store/:

packages/e2e-test-utils-playwright/node_modules/lighthouse ->
  ../../../node_modules/.store/lighthouse@12.2.2-E1oDY3hhcKvr16czLc4uyw/node_modules/lighthouse

This affects both nested patches (parent++child+version.patch) and, in monorepo/workspace setups, any packages whose dependencies are stored exclusively in .store/.

Expected behavior

patch-package should resolve the actual package location by following symlinks or by searching the .store/ directory when the traditional node_modules/ path doesn't contain the package directly.

Possible Solution

When looking up a package to patch, if the expected node_modules/<pkg> path is a symlink, follow it to find the real package directory and apply the patch there. Alternatively, add support for searching node_modules/.store/ for <pkg>@<version>-* entries.

This is related to #277 (monorepo hoisting) in that both involve packages not being at the path patch-package expects, but the root cause here is the npm linked install strategy's .store/ layout rather than workspace hoisting.

Context

npm's install-strategy=linked is an experimental feature that deduplicates packages by storing them in a content-addressed .store/ directory and creating symlinks. As this strategy matures and sees wider adoption, patch-package will need to handle this layout.

Our workaround is a custom apply-patches.mjs script that:

  1. Parses patch filenames to extract package name and version
  2. Looks up the package in node_modules/.store/<pkg>@<version>-*/node_modules/<pkg>/
  3. Rewrites diff paths in the patch to target the actual .store/ location
  4. Applies patches using git apply --ignore-whitespace

Your Environment

Software Version(s)
patch-package 8.0.0
npm 10.9.5
node 20.x+

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions