package.json dependency caret symbol - node.js

suppose in the package.json file I have my dependencies as-as -
"dependencies": {
"moment": "^2.22.2"
}
Here, are we saying that for the package "moment" we can use any of version 2.x.x functionality( i.e. we can use the new functions provided by 2.23.2 in our app, though we installed 2.22.2 on our computer) or are we saying that anyone else who uses our code of app can use any 2.x.x version of "moment" package ?

If you set:
"moment": "^2.22.2"
the user will download almost the v2.22.2. In this case you will download the v2.24.0
If you set:
"moment": "2.22.2"
the user will download exactly that version
If you set:
"moment": "~2.22.1"
the user will download almost the v2.22.1. In this case you will download the v2.22.2
You can use the functions in v2.9.9 if and only if the module respect the semver standard.
That is true the 99.999% of times.

can we use any of version 2.x.x functionality( i.e. we can use the new functions provided by 2.9.9 in our app, though we installed 2.22.2 on our computer)
Just to avoid confusion. You will not install version 2.22.2 on your computer. By saying ^2.22.2, npm will look what is the highest version of 2.x.x and install that version. You will never install version 2.22.2. You will install version 2.24, and when moment updates its packages to 2.25.0, you will install that version. So you will always have the latest verison 2.x.x installed, so you will get the functions of 2.9.9.
are we saying that anyone else who uses our code of app can use any 2.x.x version of "moment" package ?
Yes, you can verify this by checking out package-lock.json which is created by NPM and describes the exact dependency tree. https://docs.npmjs.com/files/package-lock.json
If your package.json is version 1.0.0 and you have 2.22.2 dependency on moment, and do npm install, you will see in package-lock.
{
"name": "mypackage",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
}
}
}
So everybody that installs your version 1.0.0 of your package will get moment version 2.24
why do I need to install "moment.js" again (i.e. update it) once its
installed on my computer –
You don't have to to. But the common rule is to leave node_modules out of repositories and only have package.json. So that when you publish your website to for example AWS, Azure or DigitalOcean, they will do npm install and therefore install everything, every time you publish your website.
To clarify how the flow of packages usually is
You create a package/module with specific verison
I decide to use your package
So I will do npm install (to use your package)
NPM will go through the dependency tree and install versions accordingly.
My website works and I am happy
In the meanwhile you are changing your code, and updating your package.
Few months pass and I decide to change my website. So now when I do npm install (because I updated my code), I will get your updates as well.

Related

why I can't change Typescript version even though I have downgraded the version

so previously, I installed Typecript on my new macbook by running this command
sudo npm install typescript -g
and I got Typescript version 4.7.4. and then I want to deploy the function using this command
firebase deploy
unfortunately, there is a warning like this
WARNING: You are currently running a version of TypeScript which is
not officially supported by #typescript-eslint/typescript-estree.
You may find that it works just fine, or you may not.
SUPPORTED TYPESCRIPT VERSIONS: >=3.3.1 <4.1.0
YOUR TYPESCRIPT VERSION: 4.7.4
Please only submit bug reports when using the officially supported
version.
and then I downgrade to version 4.0.7, but unfortunately that warning still exist, it seems my app is still on v4.7.4 (cached ? ) I am sure I have changed the typescript version on package.json and I also check via terminal like the image below
but why my node app still have version v.4.7.4 ? not v.4.0.7 ? what should I do?
fiuhhh....after 2 days, I finally find the solution
I have to change the dependencies and also the devDependencies, especially these dependencies in the package.json
"dependencies": {
"firebase-admin": "^10.0.2",
"firebase-functions": "^3.18.0",
},
"devDependencies": {
"#typescript-eslint/eslint-plugin": "^5.12.0",
"#typescript-eslint/parser": "^5.12.0",
"eslint": "^8.9.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.25.4",
"typescript": "^4.5.4" // <-- watch this version
},
the problem is ....it seems to me that these dependencies is tightly coupled. it can easily break if it doesn't match. so my solution is to create new project just to copy and paste those dependencies combination above with the latest version recommended by firebase. watch this video if you are confused how to initialize cloud function project
first, Update your firebase tools to the latest version using this command
sudo npm install -g firebase-tools
and change to your directory and init the project
cd desktop
mkdir forCopyPasteDependenciesOnly
firebase init
select cloud function and typescript. and then you copy those dependencies above and paste it on your problematic project
in my case, I also change the typescript globally using the recommended typescript version from the project package.json that you just initialize (4.5.4, not 4.0.7 or 4.7.4 in my case )
sudo npm uninstall -g typescript
sudo npm install -g typescript#4.5.4
and then, in your problematic project, delete your node-modules folder
and delete your package-lock.json. and finally run these 2 commands below
npm cache clean –force
npm install
and when you run firebase deploy you may see errors, but luckily it just error from eslint you just update, you can solve it easily.
I hope it helps
You installed typescript as globally on your system but you changed just in your package.json.
First you should type this npm uninstall -g typescript.
Then npm install -g typescript#your version.
After that you can uninstall your local tsc on your project.

confusion about npm install and npm update

I am learning about the differences between package.json and package-lock.json
I been experimenting on a package with only one dependency called chance
I first installed it via npm i chance#1.0.0 and the package.json has "chance": "^1.0.0" and package-lock.json has "version": "1.0.0".
Because I wanted to see the effect that the lock file has on the version, I went ahead and deleted package-lock.json and node_modules, I ran npm install, the version of chance stays the same in package.json, which is "chance": "^1.0.0". In the newly created lock file, the version of chance became "chance": {"version": "1.1.8",, so it updated itself.
I then deleted package-lock.json and node_modules again and ran npm update, the results seemed to be the same with the previous experiment – in package.json I have "^1.0.0" in package.json and "1.1.8" in package-lock.json
My questions are:
in either case, with "^1.0.0" in package.json and "1.1.8" in package-lock.json, which version of the dependency am I actually using in my project, I guess it is 1.1.8 right? so by merely looking at the versions in package.json is not enough to determine the exact version of the dependencies used in a project?
When does running npm install change the lock file? I know that if we delete the lock file, it will generate a new one with the newest versions in the allowable ranges from package.json. But are there any cases where npm install would change the lock file even if I didn't delete the lock file?
So, the answer is a bit complex. Essentially there are 2 things at play: The version of the package you want/need, and the version of the package that is installed.
When you are building a project, you probably don't care what specific version of a given dependency is. Most of the time you want the latest one, or the latest patch near a specific major version. The package.json is supposed to document what you, the developer, believe is required for your project to work. So, if you put in the package json "chance": "1.0.0", it would mean that only version 1.0.0 exactly is acceptable, and any other version is unacceptable. If you put "chance": "^1.0.0", it means any version compatible with 1.0.0 is acceptable. So 1.2 or 1.3 might also be fine, but 1.4 might introduce a change that breaks compatibility.
Once you decide what packages you want, by writing the package json, you run npm install. npm install can't always install exactly the versions you want. For example, imagine you want to install two packages: React v1.13 and momentJS v2.8. So you add these to your package json like this:
(Note: these version numbers and dependancies are not based on real React or Moment version numbers)
"momentJS" : "2.8",
"react" : "1.13"
then you run npm install. And you get an error: Package dependencies cannot be resolved. (or something like that). The problem is that React version 1.13 requires momentJS 2.9, but your package json specifies that you want version 2.8 exactly. You can't have both, so npm isn't able to resolve the conflict. A fix would be:
"momentJS" : "^2.8",
"react" : "1.13"
Now you are saying that you need a version of moment compatible with 2.8, and you are okay with npm adjusting that to satisfy other packages. Run npm install again and npm might install version 2.9, which satisfies both your requirement of "compatible with 1.8" and React, which wants 2.9. Now, the web app I'm currently working on has over 1,000 dependancies total, so npm absolutely needs to be able to adjust version numbers in order to get all of those packages to play nice.
Now there is often more than one way to solve a dependancy graph--more than one way to adjust all the version numbers to make every package happy. Your package lock file records what the current solution is and what actual packages are installed.
All the options for specifying package verions are here
Hope that helps!
Also: the second part of your question was "will npm change the lock file without me deleting it?" And the answer is: basically everytime you run npm install, npm changes the lock file. What npm does try to do is change the lock file as little as possible with each new install and keep most packages the same

Module '"buffer"' has no exported member 'Blob'

Have anyone been in this situation before ?
I run my code with CI/CD
after nest build, it gives me error :
node_modules/#types/superagent/index.d.ts:23:10 - error TS2305: Module '"buffer"' has no exported member 'Blob'. 23 import { Blob } from "buffer";
I don't know why? Please share if you got a solution for this one.
We had the same problem after upgrading nest 7.5.x to 8.0.0. The dependency "supertest" for "nestjs/testing" has a dependency on "#types/supertest" which wildcards "#types/superagent": "*", and that dependency has another wildcard dependency "#types/node": "*", but the types within #types/supertest actually require #types/node >=16.X.X.
So nestjs/testing -> supertest -> #types/supertest -> #types/superagent -> #types/node >= 16.X.X is your problem and error.
The comments mentioned are accurate because these package managers wildcard their dependencies to get the latest version of dependencies. They should but do not add peerDependencies with dependencies requirements such as "#types/node": "">=12.0.0 <16.0.0". Instead they say anything, "#types/node": "*" so the error is post package install, no npm warnings/errors. "It worked yesterday but not today" is your big red flag because when you ran npm install, with these wildcard dependencies even though you did not know it installed the latest version. Since it installed everything wildcard today, but not yesterday, it worked yesterday.
In addition, but also important is that you are have pinned #types/node <16.0.0 thus your error in combination with the other package changes.
One option: revert your package-lock.json changes and run npm ci
Another option: set your package.json dependency for #types/node to -> "#types/node": "^16.0.0",.
Another option: accept that wildcards are wrong and you don't trust what is going on there so pin the #types/superagent dependency to the one prior.
As for me and my family, we use nestjs with AWS lambda which runtime does not include nodejs 16, and not everyone on my team runs npm ci we more typically run npm install so the solution was
package.json
...
"devDependencies": {
...
"#types/node": "14.18.2",
"#types/superagent": "4.1.10",
"#types/supertest": "^2.0.11",
...
Upgrading #types/node to ^14.18.10 and typescript to ^3.9.10 worked for me.
"devDependencies": {
"#types/node": "^14.18.10",
"typescript": "^3.9.10"
},
Found on this discussion from Github
downgrading #types/superagent from v15.x.x to 14.1.14 solved the issue for me. v15 had some performance issues at the typing of this message
"npm i --save #types/superagent#4.1.14" did the trick
One tip is use npm view to get some info.
If you type
npm view #types/node
That shows the ts version compatibility. In my case, Is had to upgrade #types/node to 14.14.31, because I'm using ts 3.4.2.
if you have installed the npm, then delete the node_module file and use yarn install to add the new node_module and vice versa.

Unable to install latest version of a package that is in the NPM repo

I'm having issues with a NPM and couple of dependencies where the latest version of a package that NPM finds is different from the latest version that is actually present in the NPM repo.
I'm trying to install a package that has other dependencies, but I'm unable to because I get the "No matching version found for (package)#(version)" error. However, if I go to the NPM official site, I can see that there is in fact matching version for the package I need.
I've upgraded NPM to its latest version and I have also cleaned my NPM cache.
Edit: Some of the specific packages in question - gulp-chmod#^2.0.0, sanitize-filename#^1.6.1, generator-code#1.1.22
See if the adding the following key in package.json helps you!
"engines": {
"node": "8.1.1",
"npm": "5.0.3"
}
We can specify the node and npm version in the package.json file as shown above.
In getting the same error (for a package I just updated, typeson) and looking at my log, I see it is trying to access:
https://registry.npmjs.org/typeson
While this and https://www.npmjs.com/package/typeson are showing only up to 5.17.0, http://registry.npmjs.org/-/v1/search?text=typeson is showing the currently latest version, 5.18.0.
Maybe it can just take time to propagate through the site.
Update: In my case, it still wasn't working about an hour later, so I published a new version, and it was then immediately available.

Why use peer dependencies in npm for plugins?

Why does, for example, a Grunt plugin define its dependency on grunt as "peer dependencies"?
Why can't the plugin just have Grunt as its own dependency in grunt-plug/node_modules?
Peer dependencies are described here: https://nodejs.org/en/blog/npm/peer-dependencies/
But I don't really get it.
Example
I'm working with AppGyver Steroids at the moment which uses Grunt tasks to build my source files into a /dist/ folder to be served on a local device. I'm quite new at npm and grunt so I want to fully comprehend what is going on.
So far I get this:
[rootfolder]/package.json tells npm it depends on the grunt-steroids npm package for development:
"devDependencies": {
"grunt-steroids": "0.x"
},
Okay. Running npm install in [rootfolder] detects the dependency and installs grunt-steroids in [rootfolder]/node_modules/grunt-steroids.
Npm then reads [rootfolder]/node_modules/grunt-steroids/package.json so it can install grunt-steroids own dependencies.:
"devDependencies": {
"grunt-contrib-nodeunit": "0.3.0",
"grunt": "0.4.4"
},
"dependencies": {
"wrench": "1.5.4",
"chalk": "0.3.0",
"xml2js": "0.4.1",
"lodash": "2.4.1"
},
"peerDependencies": {
"grunt": "0.4.4",
"grunt-contrib-copy": "0.5.0",
"grunt-contrib-clean": "0.5.0",
"grunt-contrib-concat": "0.4.0",
"grunt-contrib-coffee": "0.10.1",
"grunt-contrib-sass": "0.7.3",
"grunt-extend-config": "0.9.2"
},
The "dependencies" packages are installed into [rootfolder]/node_modules/grunt-steroids/node_modules which is logical for me.
The "devDependencies" aren't installed, which I'm sure is controlled by npm detecting I'm just trying to use grunt-steroids, and not develop on it.
But then we have the "peerDependencies".
These are installed in [rootfolder]/node_modules, and I don't understand why there and not in [rootfolder]/node_modules/grunt-steroids/node_modules so that conflicts with other grunt plugins (or whatever) are avoided?
TL;DR: peerDependencies are for dependencies that are exposed to (and expected to be used by) the consuming code, as opposed to "private" dependencies that are not exposed, and are only an implementation detail.
The problem peer dependencies solve
NPM's module system is hierarchical. One big advantage for simpler scenarios is that when you install an npm package, that package brings its own dependencies with it so it will work out of the box.
But problems arise when:
Both your project and some module you are using depend on another module.
The three modules have to talk to each other.
In Example
Let's say you are building YourCoolProject and you're using both JacksModule 1.0 and JillsModule 2.0. And let's suppose that JacksModule also depends on JillsModule, but on a different version, say 1.0. As long as those 2 versions don't meet, there is no problem. The fact that JacksModule is using JillsModule below the surface is just an implementation detail. We are bundling JillsModule twice, but that's a small price to pay when we get stable software out of the box.
But now what if JacksModule exposes its dependency on JillsModule in some way. It accepts an instance of JillsClass for example... What happens when we create a new JillsClass using version 2.0 of the library and pass it along to jacksFunction? All hell will break loose! Simple things like jillsObject instanceof JillsClass will suddenly return false because jillsObject is actually an instance of another JillsClass, the 2.0 version.
How peer dependencies solve this
They tell npm
I need this package, but I need the version that is part of the
project, not some version private to my module.
When npm sees that your package is being installed into a project that does not have that dependency, or that has an incompatible version of it, it will warn the user during the installation process.
When should you use peer dependencies?
When you are building a library to be used by other projects, and
This library is using some other library, and
You expect/need the user to work with that other library as well
Common scenarios are plugins for larger frameworks. Think of things like Gulp, Grunt, Babel, Mocha, etc. If you write a Gulp plugin, you want that plugin to work with the same Gulp that the user's project is using, not with your own private version of Gulp.
I would recommend you to read the article again first. It's a bit confusing but the example with winston-mail shows you the answer why:
For example, let's pretend that winston-mail#0.2.3 specified "winston": "0.5.x" in its "dependencies" object because that's the latest version it was tested against. As an app developer, you want the latest and greatest stuff, so you look up the latest versions of winston and of winston-mail and put them in your package.json as
{
"dependencies": {
"winston": "0.6.2",
"winston-mail": "0.2.3"
}
}
But now, running npm install results in the unexpected dependency graph of
├── winston#0.6.2
└─┬ winston-mail#0.2.3
└── winston#0.5.11
In this case, it is possible to have multiple versions of a package which would cause some issues. Peer dependencies allow npm developers to make sure that the user has the specific module (in the root folder). But you're correct with the point that describing one specific version of a package would lead to issues with other packages using other versions. This issue has to do with npm developers, as the articles states
One piece of advice: peer dependency requirements, unlike those for regular dependencies, should be lenient. You should not lock your peer dependencies down to specific patch versions.
Therefore developers should follow semver for defining peerDependencies. You should open an issue for the grunt-steroids package on GitHub...
peerDependencies explained with the simplest example possible:
{
"name": "myPackage",
"dependencies": {
"foo": "^4.0.0",
"react": "^15.0.0"
}
}
{
"name": "foo"
"peerDependencies": {
"react": "^16.0.0"
}
}
running npm install in myPackage will throw an error because it is trying to install React version ^15.0.0 AND foo which is only compatible with React ^16.0.0.
peerDependencies are NOT installed.

Resources