So I need to read the package.json
before installing a new package via npm.
I am using npm for CSS components that are individually versioned and can have inter dependencies. (No javascript is delivered)
Looking for version conflicts for a bunch of dependencies I need to detect when package A
requires package [email protected]
and package B
requires package [email protected]
and deal with it.
Npm (as of version 3) deals with these issues by nesting a conflicting module deeper inside the tree. You now end up with both versions of the same module. CSS has a global namespace and a mixin (in Sasss case) would then overwrite each other and break your CSS.
This flat dependency issue is perfectly outlined in the npm blog: http://blog.npmjs.org/post/101775448305/npm-and-front-end-packaging
Even not considering our specific use case it strikes me as odd that you don't have access to the package.json
in preinstall
and postinstall
scripts. They seem to be just for that use case.
My package.json
of the package I'm installing looks like this:
{
"name": "testmodule",
"version": "0.3.6",
"description": "TODO",
"scripts": {
"preinstall": "npm i some-script && some-script",
},
"author": "TODO",
"license": "MIT"
}
Inside that some-script
package I run:
console.log( process.cwd() );
console.log( __dirname );
I then run:
~/path/to/folder $ npm i testmodule
This will result in:
$ npm i testmodule
> [email protected] preinstall /path/to/folder/node_modules/.staging/testmodule-5cc9d333
> some-script
/path/to/folder/node_modules/.staging/test-module-5cc9d333
/path/to/folder/node_modules/.staging/test-module-5cc9d333/node_modules/some-script
Now I totally get that I can't really access the root of where npm i
was ran because my script was run by a subprocess of npm and has an entirely different root.
I then thought npm root
should keep track where the actual root was for me and passed that as a parameter to my script from inside the testmodule package.json:
{
"name": "testmodule",
"version": "0.3.6",
"description": "TODO",
"scripts": {
"preinstall": "npm i some-script && some-script \"$(npm root)\"",
},
"author": "TODO",
"license": "MIT"
}
Unfortunately that also defaults back to a staging path:
/path/to/folder/node_modules/.staging/testmodule-5cc9d333/node_modules
I filed an issue with the registry but not holding my hopes up for them to get to that in time. Also my script needs to work on older npm installations.
In the meantime I came up with something like that inside my some-script
:
let pgkPath = process.cwd().split('/node_modules/')[0];
That will return /path/to/folder/
which is correct but it makes the assumption no-one runs an npm i
inside a folder incidentally named node_modules
... Seems hacky.
How can I access the path to the package.json from inside an npm script that is run via preinstall? To me that seems like something not too outrageous to ask for?
I don't understand your use-case entirely, but to answer your specific question of finding a parent package.json
from a preinstall script:
Pass $(cd .. && npm prefix)
as an argument to your script, then load ./package.json
.
npm prefix
will return the closest parent directory to contain a package.json
file, which when invoked from the ..
directory, should return the parent npm package's path.
{
"name": "testmodule",
"version": "0.3.6",
"description": "TODO",
"scripts": {
"preinstall": "npm i some-script && some-script \"$(cd .. && npm prefix)\"",
},
"author": "TODO",
"license": "MIT"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With