I'm trying to create an npm module that has a postinstall
script that will modify the user's package.json
and re-install packages. I'm almost there, but the problem I'm having is that the npm CLI runs my postinstall
script too early.
Is there a way, maybe by using Node or system level trick, to wait for the whole npm install
process to exit before my script runs? Like when npm calls my postinstall
script, at that time I can register another script to run after npm install
finishes?
What do I mean by "too early"? For example, after yarn install
, the yarn.lock
file will not accurately reflect the package.json
if my script interferes with yarn install
. However, if my script waits for yarn install
to completely finish and then runs another yarn install
, the yarn.lock
file will be accurate and further yarn install
commands will output "Already up-to-date".
2 Answers
Answers 1
postInstall
as you have found out has very unusual way of execution and bugged in some versions of npm (all pre npm 3) , This was fixed in the later versions So first of all make sure your npm version is up to date; If it is you have 2 options that I can give you off the top of my head,
Option 1
This is the most simplest solution, use this script, it's pretty self explanatory it will install everything and to be on the safe side give the post install a once over. Not the most ideal solution but it should work without issues.
#!/bin/bash npm install npm run postinstall
Option 2
Try moving your devDependencies
to dependencies
if possible, for some users this seem to fix the postInstall
issue. But I don't recommend it devDependencies
are there for a reason.
UPDATE
Ok, I get the issue now, but it should be covered with a slight variation to the option 1's script. Since your postinstall script can already handle the modification and re-installation.
#!/bin/bash npm install cd (<path to your modue> && npm run postinstall)
Answers 2
Consider tempering directly with the package.json as bad practice, because Devs will no longer be in control of the packages they have installed, or even their project name.
Therefore, packages should instead request the Dev to change the package.json during installation and offer a method to enable Devs for a dry-run of the changes that will be made.
TLDR; make sure to give full consent to the Dev for any tempering with the package.json.
That's why I think alternative methods are better than using a postinstall script. The most minimal solution I have come up with:
myinstall.js
const exec = require('child_process').exec; exec('npm run install').on('exit', () => exec('npm run mypostinstall'));
package.json
"scripts": { "myinstall": "node myinstall.js", "mypostinstall": "echo \"myPostinstall called\"" },
Set the mypostinstall
script equal to the postinstall
.
Note: in the example above there is no error handling, no text is displayed and there is no actual write to the package.json. It is pure for illustration on how to do execute code after npm install
. The reason no text is being displayed is due calling exec
, for which a new process is called with it's "personal" stdout. Alternatively use fork
, more info can be found here at the node documentation.
I have attempted to call npm install
instead of npm run myinstall
by setting "install": "node myinstall.js"
. However now the exec('npm run install')
will recursively call itself.
0 comments:
Post a Comment