volta-cli / volta

Volta: JS Toolchains as Code. ⚡
https://volta.sh
Other
10.87k stars 227 forks source link

Cannot link multiple packages #1019

Open hansottowirtz opened 3 years ago

hansottowirtz commented 3 years ago

When running:

npm link pkg1 pkg2

Volta logs: note: Volta is processing each package separately

It seems like npm link pkg1 and npm link pkg2 are then run in series, but this does not work, only pkg2 is linked. When linking multiple packages you need to run it as one command or the second command overrides the first command.

charlespierce commented 3 years ago

@hansottowirtz That's very strange, there's no reason I can think of why running the two commands should cause the first one to fail / be overwritten. A couple questions:

hansottowirtz commented 3 years ago

@charlespierce I've also experienced this when using npm without Volta, I always assumed it was a thing with npm link. (namely, npm i overrides all links, and you always need to link multiple packages with npm link at once)

I'm using npm 7.20.6. The packages I'm trying to link do not depend on each other. They're not public but I can reproduce with public packages:

Repro:

git clone https://github.com/ljharb/is-string
git clone https://github.com/ljharb/is-nan
cd is-string && npm i && npm link
cd ../is-nan && npm i && npm link
mkdir repro
cd repro
npm init -y
npm i is-string is-nan
npm link is-string is-nan
ls -alh node_modules

The last ls results in:

total 8
drwxr-xr-x   7 <user>  staff   224B Sep  1 23:15 .
drwxr-xr-x   5 <user>  staff   160B Sep  1 23:15 ..
-rw-r--r--   1 <user>  staff   2.9K Sep  1 23:15 .package-lock.json
drwxr-xr-x  13 <user>  staff   416B Sep  1 23:15 has-symbols
drwxr-xr-x  11 <user>  staff   352B Sep  1 23:15 has-tostringtag
lrwxr-xr-x   1 <user>  staff    12B Sep  1 23:15 is-nan -> ../../is-nan
drwxr-xr-x  12 <user>  staff   384B Sep  1 23:15 is-string

Running npm link is-string is-nan results in is-string being linked and is-nan not being linked.

In an empty repository with no package.json, npm link is-string is-nan does however link both packages.

charlespierce commented 3 years ago

@hansottowirtz Interesting, thanks for those reproduction steps! It looks like that's actually a long-standing bug / issue with npm itself: https://github.com/npm/cli/issues/3568 (which appears to have existed for at least 3 years :scream:

Their suggestion for fixing it appears to be to use --save on the npm link command, which will actually write the changes to package.json and package-lock.json. That doesn't seem ideal, but would work short-term for the Volta use-case. For a better fix, we'll need to figure out if there's a way we can do the link with all packages simultaneously while at the same time splitting them out the way Volta needs. Unfortunately, npm link is an overloaded command that does a lot of different things all at once, so it's tricky to make it work.

hansottowirtz commented 2 years ago

@charlespierce Interesting, thanks for finding that issue. This one also seems relevant: https://github.com/npm/cli/issues/2380.

I'm not familiar with Volta internals, but would it possible to bypass the overloading of npm link temporarily?

charlespierce commented 2 years ago

Yes, you can override the interception of npm link by setting the environment variable VOLTA_UNSAFE_GLOBAL=1. However, this comes with some caveats:

  1. npm link is a very overloaded command that does a lot, some of that won't work. For example, if a local package has a bin value and you npm link inside of it, normally that would effectively install it globally, making the binary available on your PATH. With VOLTA_UNSAFE_GLOBAL, that package will be installed in the bin directory under the Node version, which isn't generically on your PATH, so it won't be available.
  2. Similarly, since the default behavior with Volta's intervention is to link the package into the Node installation directory, it will be tied to that specific version of Node. This means in order to successfully npm link <my-package> in another project, they both need to be using the exact same Node version.
Rusinas commented 1 year ago

Any updates on this?

jmlee2k commented 1 year ago

UPDATE - sorry, I jumped the gun - I'm still having the same issue with 1.1.0.

@Rusinas @charlespierce I just had a similar issue with volta 1.0.5 (npm linking multiple packages resulted in only one being symlinked), but it appears to work properly with volta 1.1.0.

natcl commented 4 months ago

I have a similar issue here with 1.1.1, seems like when I try linking multiple packages it installs the package pinned in package.json instead of pointing to my local package on disk.

Example with 2 packages:

npm link @company/package1 @company/package2

lrwxr-xr-x    1 user  1622570660    93B  6 mai 16:26 package1 -> ../../../../../../.volta/tools/image/node/18.20.2/lib/node_modules/@company/package1
lrwxr-xr-x    1 user  1622570660   104B  6 mai 16:26 package2 -> ../../../../../../.volta/tools/image/node/18.20.2/lib/node_modules/@company/package2

When linking a single package, the link is ok:

npm link @company/package1
lrwxr-xr-x    1 user  1622570660     21  6 mai 16:44 package1 -> ../../../package1