Skip to content

This repository demonstrates a bug in npm-ci when installing an optional, platform-specific transitive dependency.

Notifications You must be signed in to change notification settings

restjohn/issues.npm.shrinkwrap_optional_dep

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

npm Transitive OS-Specific Shrinkwrap Dependency Error

This repository demonstrates a bug in the npm ci command which produces an error when running the command in a package that publishes a shrinkwrap, and that has a transitive, optional dependency with an OS constraint.

Project Contents

  • lib1.shrinkwrap - This is a package published with a shrinkwrap file, with a transitive, OS-specific dependency. The dependency, in this case, is mocha, which depends on chokidar, which optionally depends on fsevents, which has a constraint to the darwin (macOS) platform.
  • lib1.lock - This is essentially the the same package as above, but using a package-lock.json, published without a shrinkwrap file.
  • app1 - This is a root package that depends on lib1.shrinkwrap.
  • app2 - This is a root package that depends on lib1.lock.

Reproducing the Bug

The bug was reproduced using npm 10.8.1, the latest at the time of this writing.

If you're on a Linux or Windows platform, simply descend into the app1 directory and run npm ci. This should produce an error like

app1 % npm ci
npm error code EBADPLATFORM
npm error notsup Unsupported platform for [email protected]: wanted {"os":"darwin"} (current: {"os":"linux"})
npm error notsup Valid os:  darwin
npm error notsup Actual os: linux

npm error A complete log of this run can be found in: /root/.npm/_logs/2024-07-02T13_12_08_752Z-debug-0.log

If you're on macOS, you can use a node docker image something like the following, from the root of this repository.

docker run -it --entrypoint /bin/bash -v $(pwd):/shrinkwrap_optional_dep node:20-slim
cd /shrinkwrap_optional_dep/app1
npm ci

Other Notes

Dev Dependency

Note that the path to the OS-constrained dependency, fsevents, also runs through a devDependencies dependency, so npm should not be attempting to install fsevents due to that condition, let alone the OS constraint and optional dependency status.

Missing optional Flag

Observe that the app1 package-lock contains an entry for the transitive, optional fsevents dependency. However, that entry does not contain the "optional": true key-value, as does the lib.shrinkwrap shrinkwrap file.

    "node_modules/@restjohn/issues.transitive-optional-dep.lib1.shrinkwrap/node_modules/fsevents": {
      "version": "2.3.3",
      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
      "extraneous": true,
      "hasInstallScript": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
      }
    },

If you manually add "optional": true to the above block in the app1 package-lock, npm ci for the app1 package on a non-Darwin platform succeeds.

Without Shrinkwrap

Running npm ci in the app2 package produces no error, because app2 depends on the published lib1.lock package, which does not use npm-shrinkwrap.json as lib1.shrinkwrap does.

npm install Works

Running npm install in the app1 package on a non-Darwin platform produces no error.

Package Tarball Works

Installing lib1.shrinkwrap from a package tarball produces no error. You can test this from your macOS platform easiest by using the Docker method described above. From the root repository directory in a macOS shell, execute the following commands.

npm pack ./lib1.shrinkwrap
cd app1
npm i ../restjohn-issues.transitive-optional-dep.lib1.shrinkwrap-1.0.0.tgz
cd ..

Then, use a Docker container to test npm ci.

docker run -it --entrypoint /bin/bash -v $(pwd):/working node:20-slim
cd /working/app1
npm ci

Remote Package Tarball Works

Installing lib1.shrinkwrap in app1 as a remote tarball produces no error from npm ci. You can test this easily by using the http-server package. From the repository root directory in your macOS shell, execute the following commands.

npm pack ./lib1.shrinkwrap
npm i -g http-server
http-server -a 127.0.0.1 .

http-server is now running in the foreground in that shell. Open another shell window and execute the following commands from the root repository directory.

cd app1
npm i http://127.0.0.1:8080/restjohn-issues.transitive-optional-dep.lib1.shrinkwrap-1.0.0.tgz
cd ..
docker run -it --entrypoint /bin/bash -v $(pwd):/working node:20-slim
cd /working/app1
npm ci

Verdaccio Registry Works

About

This repository demonstrates a bug in npm-ci when installing an optional, platform-specific transitive dependency.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published