NPM package.json convert * asterisk to version - npm

I have a package.json from my template with several dependencies.
If I want to create a new project, I use my template.
But how to convert all * (asterisk sign / latest version) to a fixed version which is downloaded from npm. npm install --save does not work.
Before npm install (template package.json)
"devDependencies": {
"one": "*",
"two": "*",
"three": "*"
}
should convert to following by npm i --save.
"devDependencies": {
"one": "1.0.0",
"two": "2.0.0",
"three": "3.0.0"
}
How to overwrite the version string?

As per the documentation
(*) --> Matches any version
("") --> (just an empty string) Same as *
The workaround of this issue is shrinkwrap(Read documentation for further information). You can use this command npm shrinkwrap.That creats a npm-shrinkwrap.json file. When you run the command,You get the following comments on console (npm notice package-lock.json has been renamed to npm-shrinkwrap.json. npm-shrinkwrap.json will be used for future installations.). And that will gave the updated package version whatever you have in package.json.

Use npm list --depth=0 to see what versions were installed by installing 'latest' from your template. You should get something like this:
├── #angular-devkit/architect#0.1501.1
├── #angular-devkit/build-angular#15.1.1
├── #angular-eslint/builder#15.2.0
Copy, modify and paste output into your package.json. Then you should probably remove node_modules and check if running npm ci works properly.
Notes:
This is how you should specify wanted versions in package.json:
"react": "^16.0.0" // carat: allow 16.1.0
"react": "~16.0.0" // tilde: allow 16.0.1
"react": "16.0.0" // exact: only 16.0.0
If your template is fairly complicated, it is highly unlikly that such workflow would be convenient. I would advise having specific versions in the template carefully combined, so that they work. Then, once every couple of months, you should (again, carefully) updgrade libraries in your template. Otherwise, sooner or later you are going to install two latest version of some conflicting pakages.

Related

How to "npm install packageX" while respecting package-lock.json

I want to update a dependency (packageX) without changing a locked dependency of that package, (packageY). In my package-lock.json, I have:
"packageX": {
"requires": {
"packageY": "1.0.0",
}
},
Each time I do "npm install packageX," I'd like to update packageX but have packageY stay on the defined version. How can I do that?
There is no way to do this, may be this link can explain better https://dev.to/saurabhdaware/but-what-the-hell-is-package-lock-json-b04
The story about package.json vs package-lock.json is tricky: npm install does not ignore package.json versions, nor does it ignore the package-lock.json. What it does is verify that the package.json and package-lock.json correspond to each other. That is, if the semver versions described in package.json fit with the locked versions in package-lock.json, npm install will use the latter completely, just like npm ci would.
Now, if you change package.json such that the versions in package-lock.json are no longer valid, your npm install will be treated as if you'd done npm install some-pkg#x.y.z, where x.y.z is the new version in the package.json for some-package.

NPM: To install a package along with its own devDeps

I am just getting myself familiar with command line tools like npm. I've been searching around for the answer but was not able to find a clear one.
What I am trying to do is to install materialize-css package into my test package, as well as its devDependencies, like "autoprefixer". This is materializeCSS's package.json file.
Here's what I do:
Under my newly created and blank folder "testProject", I use npm init to create a package.json file for my test package:
{
"name": "create_project",
"version": "1.0.0",
"description": "Setting up a project",
"main": "index.html",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "shenk wen",
"license": "MIT"
}
Then, I do
npm install materialize-css
I was expecting the above command would install all the dependencies and devDependencies of materialize-css, but only the dependencies is being installed. I read this question and the accepted answer suggests adding --dev to the command. But that seems not the answer I am looking for because --dev would only make materialize-css a devDependency of my test package, but not installing its own devDependencies. The other answers are not so straightforward. Is there any parameter I can use to achieve this? Or do I have to change the env_variable which I don't know how to?
In older npm versions, 'npm install --dev' installed all devDependencies of all your dependencies. This also used to work in a recursive fashion, so you end up downloading also devDependencies of devDependencies of your dependencies and so on. This resulted in enormously long install time / download size.
Also, the purpose of the feature is questionable: Why should you care about devDeps of your deps? For these reasons --dev was removed from npm:
https://github.com/npm/npm/issues/5554
Current behavior for 'npm install' is: install all deps and devDeps for the 'main' package (the one you 'npm install'-ed in the first place), but when recursing, install only deps (and no devDeps).
If you want to install & save the dependency to your package.json, you should use --save or --save-dev, I don't think --dev does this.
If you want the devDependencies of a module you've installed as a dependency to your project, you almost certainly want to git clone that module's repo or fork it instead. When you run npm install in your cloned repo, that will also install all of the module's devDependencies.
(I'm not a developer by trade and my npm-fu was a bit rusty, so I confused myself about what I was trying to do. Tomas Kulich's question "Why should you care about devDeps of your deps?" helped me realize the error of my ways.)

npm issues with UNMET PEER DEPENDENCY, related to react-native

I think I'm confused as to how npm manages dependencies. I see this:
npm list react-native
project#0.0.1 /Users/me/workspace/project
└── UNMET PEER DEPENDENCY react-native#0.15.0
npm ERR! peer dep missing: react-native#^0.13.2, required by react-native-dialogs#0.0.5
npm ERR! code 1
So I try... but I get:
npm install react-native#0.15.0
....
project#0.0.1 /Users/me/workspace/project
└─┬ UNMET PEER DEPENDENCY react-native#0.15.0
└── react-tools#0.14.0-beta1 (git+https://github.com/facebook/react.git#b4e74e38e43ac53af8acd62c78c9213be0194245)
npm WARN EPEERINVALID react-native-dialogs#0.0.5 requires a peer of react-native#^0.13.2 but none was installed.
npm ERR! code 1
My package.json:
{
"name": "project",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "react-native start"
},
"dependencies": {
"apsl-react-native-button": "^2.1.0",
"base-64": "^0.1.0",
"es6-react-mixins": "^0.2.1",
"fifo": "^2.3.0",
"money-math": "^2.2.0",
"react-native": "^0.15.0",
"react-native-dropdown-android": "0.0.4",
"react-native-lightbox": "^0.5.0",
"react-native-mail": "^0.2.4",
"react-native-router-flux": "^0.3.4",
"react-native-simpledialog-android": "^1.0.2",
"react-native-swiper": "^1.3.0",
"superagent": "^1.4.0",
"tcomb-form-native": "^0.3.0",
"utf8": "^2.1.1",
"react-native-facebook-login": "^1.0.0"
}
}
I know it's an old question, but a response can still be useful for others seeing this in the future.
Explanation of the issue
In your package.json, you are installing the dependency react-native-dialogs#0.0.5 which is as well expecting as a peerDependency the module: react-native#^0.13.2. Since that project is public, it can be verified in their package.json file:
"peerDependencies": {
"react-native": "^0.13.2"
}
The first part of this statement, is the module name, and the second part, the supported version range.
This means that the root module should provide such dependency and in such version range, in order for the installation to succeed with no errors. In this case, it's stating react-native dependency, and in the ^0.13.2 version range.
Now, in your package.json, you are listing the dependency:
"react-native": "^0.15.0",
So why is it not working? The ^ (caret) in version range should include all patch and minor versions in the same major, right? (ie. in "^X.Y.Z" range, all X.*.* should work, right?). Well, turns out this isn't true for pre-1.x ranges. For 0.x ranges, the ^ caret only covers patch versions inside the range (source: NPM docs).
Therefore, per this rule, "^0.15.0" is not in the range of "^0.13.2", so this is why you get the UNMET PEER DEPENDENCY error.
Possible solutions
You have a few options here.
Provide the expected peer dependency
The most straightforward one, is providing the expected peer dependency in a version that is in the expected version range.
So you could use the same version range, in this case: "^0.13.2". Or specify an exact version as well, for example: "0.13.2".
Tip: you can check all versions that match the requested range for a given package, using this utility https://semver.npmjs.com/.
For this case, the only version that exists and matches the range is "0.13.2", but there could've been more (ie. "0.13.3" could've been fine as well, if it existed. But "0.14.0" or "0.12.0" won't work, as explained above)
Update your module dependency
In many cases the original module gets upgraded, and changes may include supporting different or more broad peerDependencies packages/versions.
As of today, I can see in the package.json on the project master branch, that the current module version is 1.1.1 and the peerDependencies have been removed, so upgrading your "react-native-dialogs" dependency version ^0.0.5 -> ^1.1.1 will do the job for this scenario.
But, what if this didn't happen, or if you didn't want to upgrade to the latest version?Let's explore more options.
Change the module itself that you want to depend on
In case that providing the dependency version requested as a peerDependency by a module you use conflicts with your requirements, and upgrading this dependency to a newer version that removes this constraint doesn't work for you.
The allowed range "^0.13.2" might be quite limited, ie. it won't support version 0.14.0 and onwards. The reasoning behind this, could be based on compatibilty issues, or maybe just a lack of awareness in allowing/supporting for more versions. There could happen to exist other versions that can work fine, but the original developer did not take the extra steps to include them.
So you just want to continue using this exact module as is, but allow a newer react-native version.
Imagining the original scenario, that 0.0.5 was the current latest version in the master branch, it could make sense raising this as an issue to the original module repo, and/or submit them a PR proposing a broader supported range. For example:
"peerDependencies": {
"react-native": "< 1.0.0"
}
The range "< 1.0.0" would now allow the "^0.15.2" version range.
What if you didn't want to allow all the 0.x versions? Then you could use a more narrow range, such as: "> 0.4.0 < 1.0.0". Take a look at NPM semver docs for syntax, a lot more possibilities are allowed too.
Don't use that module at all / Build your own
It can happen that the original module can be abandoned, have bugs, or just not work for your all of your requirements. In this case, you can look for a some alternative available in the community, or even build one yourself.
Since this module is public you can even fork the project and upload a new package version yourself with the changes you want (you'll have to use a different package name of course).
Try the "--save" argument for "npm install" command, like:
npm install react-native#0.15.0 --save

npm install bluebird doesn't install module

I am attempting to use bluebird in a node application. I have tried adding bluebird to my package.json, as well as installing via npm install bluebird.
My package.json dependencies:
"dependencies": {
"express": "visionmedia/express",
"mocha": "visionmedia/mocha",
"bluebird": "petkaantonov/bluebird",
"waitjs": "elving/wait"
}
Regardless of what method I try, it doesn't look like the module is actually being installed. After I run the install; in node_modules\bluebird there are only 4 files:
changelog.md
LICENSE
package.json
READEME.md
As you can see, there is no code pulled down which would actually comprise the module. The package.json for bluebird does not have a dependencies section, so I am not sure if maybe the package.json file for the module is incorrect?
I've pasted the package.json contents on pastebin for easier viewing.
I'm pretty stumped why this is not installing correctly.
npm version: 2.11.3.
node version: v0.12.7.
Thanks for any help.
The dependencies section of the packages.json should have version numbers as the module values, not git repos.
If you are having this issue, remove your dependcies section from package.json and then install each module using npm install {module name} -save.
My package.json ended up looking like:
"dependencies": {
"bluebird": "^2.9.34",
"express": "^4.13.1",
"mocha": "^2.2.5",
"waitjs": "^0.2.0"
}
Thanks to untogethered on reddit for the answer.
First thing to always try with module install problems is:
npm cache clean
Then try and install again, also remember to remove the bad install at node_modules/bluebird

Install only one package from package.json?

Suppose that somewhere in my package.json I have:
"dependencies": {
"bower": "1.0.0",
// zillion other dependencies
}
Is there a way to make npm install only bower#1.0.0 from my package.json? Like so: npm install --only bower.
My goal is to make npm install and bower install run simultaneously.
As a workaround you may use something like:
$ node -pe "require('./package').dependencies.bower"
// → 1.0.0
$ npm install bower#$(node -pe "require('./package').dependencies.bower")
// npm install bower#1.0.0
// or with jq
$ npm install bower#$(< package.json jq -r '.dependencies.bower')
Where -e/--eval flag evaluates passed string and -p/--print prints result of eval.
💡 Please consider other answers as well since this one may be outdated.
As #atalantus noted in comment, the accepted answer doesn't work on newer version of NPM. Working solution for newer versions (verified on NPM 6.13.4) is:
npm install --no-package-lock --no-save bower#1.0.0
This will install bower and all its dependencies, but prevents installation of anything else you might have in package.json. It also doesn't create or modify existing package-lock.json.
From npm documentation:
The --no-package-lock argument will prevent npm from creating a package-lock.json file. When running with package-lock's disabled npm will not automatically prune your node modules when installing.
--no-save: Prevents saving to dependencies.
Combining this with Anton Rudeshko's approach to find out version in package.json, the final solution is:
VERSION_BOWER=`node -p -e "require('./package.json').dependencies.bower"`
npm install --no-package-lock --no-save bower#"$VERSION_BOWER"
Update 2023
Alternative solution I've just used is to temporarily modify package.json to only keep the dependency you need. That can be done quite easily with help of jq
Given package.json
{
"name": "sample",
"main": "src/index.js",
"dependencies": {
"bower": "1.0.0",
"foo": "^1.2.3",
"bar": "^4.5.6",
},
"devDependencies": {
"baz": "^10.20.30",
}
}
Let's first modify it with jq to only keep bower
cat package.json| jq 'del(.devDependencies) | .dependencies |= {bower:.bower}'
Gives us
{
"name": "sample",
"main": "src/index.js",
"dependencies": {
"bower": "1.0.0"
}
}
by deleting devDependencies completely and leaving only bower in dependencies.
Next up you would want to overwrite package.json with this new, version, but you can't do it directly like this
cat package.json | jq 'del(.devDependencies) | .dependencies |= {bower:.bower}' > package.json
because the file gets overwritten before it's fully read. Instead you need to buffer the output stream of jq command, simplest solution just storing it in variable, and then overwriting the original file
updated=`cat package.json | jq 'del(.devDependencies) | .dependencies |= {bower:.bower}'`
echo $updated > package.json
And package.json now reads:
cat package.json
{
"name": "sample",
"main": "src/index.js",
"dependencies": {
"bower": "1.0.0"
}
}
Run npm install now and you only install bower#1.0.0.
Obviously not always we can afford to modify the file, but you could also back-up the original file, etc. Main point is here how to easily modify json file thanks to jq rather than playing magic tricks with sed :-)
Seeing as with newer versions of NPM the previous solutions don't work anymore, I came up with this:
npm i -g --prefix=$(pwd) bower # $(pwd) = current directory, UNIX only
node bin/bower
Installing a package globally allows you to specify a "prefix" - a directory where the package will be installed. Here I just put the current directory as the folder I want the package to appear in. In CI, this will probably be your repo root.
Keep in mind this will ignore your package.json version and just download the latest one. If you need a specific version, just use bower#someversion instead.
An alternative solution is just rm package.json && npm i bower, or mv package.json _package.json && npm i bower if you want to restore it later