We have to support 5 different cases with lifecycle scripts (prepare
and prepublish
) in node module based formulas. These are sorted by increasing difficulty / complexity to support:
- arbitrary download location with no
prepare
(orprepublish
) script: trivial to handle - npm registry tarball download (already prepared) with a
prepare
script, which could be run a second time without failure: runningprepare
twice would be unnecessary but wouldn't break anything - npm registry tarball download (already prepared) with a
prepare
script, which fails when run a second time (e.g. mkdir fails on already existing directory):--ignore-scripts
is required fornpm pack
(and if we want this case to be rooted through the bundledDependencies branch for consistency we would need to pass--production
to the first localnpm install
(because--ignore-scripts
won't work here, see npm background#1+4)) - source tarball downloads (not already prepared), but we don't want to run
prepare
(e.g. formula implements it's own logic): same a 3. - source tarball downloads (not already prepared), we want
prepare
to be executed (prepare_required
is set): we have to install all deps (because they could be required to execute theprepare
script) beforenpm pack
by doing a local npm installation. Because said installation already executesprepare
(see npm background#2) we still have to pass--ignore-scripts
tonpm pack
(because executingprepare
twice would be unnecessary and could even fail in some cases (e.g mkdir))
Supported cases by language/node
version:
- Old
npm@<=4
(node <=7) version: 1, 2, 5 (3 + 4 will fail in alllanguage/node
versions before #2826) - current version: 1, 2, 3, 4
- this PR: 1, 2, 3, 4, 5 (all)
npm background:
- passing
--ignore-scrips
to a command prevents all lifecycle scripts from being executed, even the lifecycle scripts from deps installed by this step (which is problematic if you want to use it to only prevent theprepare
/prepublish
script of the toplevel module from being executed, but accidentally are breaking e.g. the compilation of native addons in the deps with it) prepare
(andnpm@4+
deprecatedprepublish
) is run fornpm pack
(andnpm publish
). It is also run for local npm installation:npm install
without argument to install all deps of a module according topackage.json
ornpm install <moduleName>
to install a module to the localnode_modules
folder. (It was also run innpm@<4
for our oldnpm install -g --prefix=<path> <folder>
method).- But
prepare
is NOT run for global npm registry installations (npm install -g <moduleName>
) and installation from a local tarbal (npm install -g --prefix=<path> <pathToPackedTarball>
), which we do now. - Passing
--production
(to not instal devDeps) to any localnpm install
call will also preventprepare
scripts from being executed (because they might require devDeps). Unfortunately this behavior is not documented well in npms lifecycle script docs. - The new
prepublishOnly
doesn't affect us, because it's only run beforenpm publish
and NOT even beforenpm pack
postinstall
(also otherinstall
lifecycle scripts) is run AFTER anynpm install
command (local and global from any sources), but it shouldn't hurt us because npm registry tarballs are not already postinstalled and running it twice for our local install and the global prefix install wouldn't hurt, because its run AFTER install in the libexec directory at the 2nd run, which shouldn't conflict.
different installations method:
npm pack
only toplevel module (with empty dep tree) and installnpm i -g --prefix=libexec
it to libexec prefix (current version): doesn't supportprepare
(prepublish
) scripts at all, quite hacky workaround for the npm@5 symlinks issues,npm pack
is not designed to be run on an empty dep tree, but seems to work as long as no lifecycle scripts are involved- install all dependencies beforehand (which executes
prepare
), pack everything in a self-contained package usingnpm pack
with thebundledDependencies
package.json
rewrite and then installnpm i -g --prefix=libexec
it to libexec, without the need to handle deps in this last step (partly done in this PR for case 5): This matches exactly what the prenpm@<=4
(node <=7) version oflanguage/node
had done in npm internally, is more npm supported (runningnpm pack
on a complete dep tree) and it supportsprepare
scripts out of the box.