npm prune fails with error "sh: node-gyp-build: command not found"

What I Wanted to Do

Use the prune option to remove packages which should not be there

What Happened Instead

prune fails with the error sh: node-gyp-build: command not found if it tries to build a pkg which uses node-gyp.

Reproduction Steps

mkdir prunetest
cd prunetest/
npm init -y
npm i leveldown
rm -rf node_modules/
npm i
rm -rf node_modules/
npm prune

Details

npm install with an empty node_modules dir works fine, building the node-gyp part of leveldown in the example above without problems.

However npm prune attempts to do the install and fails with this error:

$ npm prune

> leveldown@5.1.1 install node_modules/leveldown
> node-gyp-build

sh: node-gyp-build: command not found
npm WARN prunetest@1.0.0 No description
npm WARN prunetest@1.0.0 No repository field.

npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! leveldown@5.1.1 install: `node-gyp-build`
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the leveldown@5.1.1 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/gavin/.npm/_logs/2019-08-01T14_35_09_133Z-debug.log

NOTE - if you run npm install first, so the leveldown module is already there, npm prune does not error.

IMO prune should either successfully install the missing package, or it should not attempt to install missing things and only remove packages which are not referenced in package.json or package-lock.json.

Platform Info

$ node -v
v10.16.0

$ npm -v
6.10.2

$ npm --versions
<!-- paste output here -->
{ prunetest: '1.0.0',
  npm: '6.4.1',
  ares: '1.15.0',
  brotli: '1.0.7',
  cldr: '35.1',
  http_parser: '2.8.0',
  icu: '64.2',
  modules: '64',
  napi: '4',
  nghttp2: '1.34.0',
  node: '10.16.0',
  openssl: '1.1.1b',
  tz: '2019a',
  unicode: '12.1',
  uv: '1.28.0',
  v8: '6.8.275.32-node.52',
  zlib: '1.2.11' }

$ node -p process.platform
<!-- paste output here -->
darwin

Yeah, really the fact that npm prune can ever add a package is kind of a confusing side effect. npm v7 won’t do this, but I’m not sure how easy it’d be to make npm prune function properly with a missing node_modules folder without a pretty significant refactor.

Am I right in thinking that npm v6 is much more aggressive at removing packages which should not be there when you run npm install than earlier versions were? Our CI scripts run npm prune as a matter of course when switching between branches in order to make sure no unwanted packages are left in node_modules, but it seems like install also mostly takes care of this now?

If so, although the behaviour of prune is annoying, we can probably just stop using it and stick to install or maybe ci.