How to install specific version of yarn using the npm API - npm

I want to download a specific version of yarn by using the npm api
How can I achieve this?

After looking through the NPM Registry API, it looks like it would be pretty simple to do that.
GET: https://registry.npmjs.org/<package> returns a JSON object with a versions field and for each version there is a dist field which has a URL to that package's tarball.
If you know the version ahead of time, GET: https://registry.npmjs.org/<package>/<version> would also work.
If you just want the tarball straight up, the format for the URL for getting a package's tarball is https://registry.npmjs.org/<name>/-/<name>-<version>.tgz. Although the registry documentation says that this might not always be true.

Related

How to get the version of a remote npm package using a bin script

I'm trying to set up an npx script to create a template project.
In package.json I have:
"bin": {
"init": "bin/init"
}
In the init script I'm using tag='v'$(npm pkg get version | tr -d '"') to get the version of the package. I then use git clone --depth 1 --branch $tag https://github.com/matriarx/typescript.git to clone that specific repository for that specific tag.
When I do yarn link and try use it locally, from within that specific project, it works because it's able to correctly pick up the package.json version. So the above only works if it's run inside an existing project. However that's not what I want to do.
I want to enable someone to run it even if they have nothing locally, by simply doing npx #matriarx/typescript init and it should create the new project by cloning it. More than that I want them to be able to clone any specific version by using npx #matriarx/typescript#0.0.1 init in order to clone a specific version.
However it seems that anything I try is only able to get the version from a local package.json that already exists.
I could just clone the current existing repository without specifying any tag, but that would defeat the point of having releases, then it would just clone any current code completely disregarding the release. So it has to clone the tagged release.
How can I get the remote package version stored on npm from the bin script without having anything locally before hand?
Alternatively is there a better way to do what I'm trying to do?
EDIT: I ended up just hardcoding the version in the script, which works but it sucks because it's tedious to have to update it every time I bump the version. Though for now I still don't know a better way to do it.
After some more time messing around I figured out there is a standard way of doing it, at least since npm 7.
If you have a project like example then you can create a completely separate project called create-example with a bin script.
When you use npm init example, npm will automatically search for a package prefixed with "create-" and execute its main bin script. So when running npm init example it will search for that create-example package and execute the bin script, which will install the example package.
This is how most of the bigger packages like react and next do it.
This approach comes with some disadvantages that I really don't like, for example it will show the incorrect dependencies on npm and it will cause you to have to maintain multiple projects and semvers on different projects. However it will also allow you to create a clean separation between the actual project and the installation of that project.
For some projects it might also make a lot more sense. For example if you have a project that doesn't have a package.json at all and you want to create a setup for it, it wouldn't make sense to create an npm package inside that project just for that. Instead you can create a separate "create-project" package just to set it up and keep npm out of the actual project. In other words it gives you a neat way to create bin scripts for a completely separate project that doesn't have anything to do with npm.
You could also just have created a normal shell script and execute it using curl but I guess npm just gives you another way to do it.
You still have to hardcode the version in that "create-project" package, I still have not seen a way to automatically determine the version from a remote package. The only way I've managed to do that is to completely download the package, get the version, then delete it, but that would be terrible for people with a slower internet connection or limited data.

Use different versions of the same package in dev or prod?

(not a native speaker, sorry if things don't seems clear)
We are devs for a clients and we work with others devs from another company. The other devs make us a package that we sometimes change this in it, then submit the changes in a pull request.
So we end up having a local version of the package and the official version. And so we want to use the local version in dev (where we might make little changes in the package to match what the client want), and the official in prod (where our changes and other devs changes are merges).
I will show an example that don't work but that can help understand the idea:
[...]
"dependencies"{
[...]
"package":"prod-package"
},
"devDependencies"{
[...]
"package":"local/version/of/package"
},
and so, we should have this:
npm build # use local/version/of/package
npm build --prod # use prod-package
I'm not really good with npm (in fact, beside npm install and npm remove, I basically know nothing), so I might ask something obvious, but I can't find the answer anywere.
Have you tried using npm-link to link to the local version of the package you are consuming? That way, you could still commit your changes to the package back to the vendor.
https://docs.npmjs.com/cli/v8/commands/npm-link
You would essentially run npm link in the checked-out-from-VCS (git?) package folder, then you switch back to your project where you are consuming that package and run npm link {name-of-npm-package}
This would allow you to develop on that version locally, make your changes (and they will show up on VCS for easy pull request management).

NPM lockfiles/shrinkwrap get random "dl" parameter tacked on to the "resolved" URL

Our company uses an Artifactory repository for storing internally-published packages and as a proxy for the NPM registry. Sometimes the resolved field in lockfiles/shrinkwrap files is as expected, containing URLs for our internal repository, but occasionally they show up as something like this (line break added for clarity):
https://our.repository.com/artifactory/api/npm/some-repo/lodash/-/lodash-3.10.1.tgz
?dl=https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz
Then, from pull request to pull requests, these dl parameters constantly oscillate to being present or removed depending on which developer does an npm install, leading to a lot of pull request & commit noise.
I'm guessing it's Artifactory that's adding this dl param, since I fail to see it in a code search in the npm code base.
Why does this happen? Can we disable this behavior? And is it safe to strip this parameter as a postshrinkwrap script workaround?
I think the root of your problem is likely caching.
NPM caches packages that have been downloaded, so they don't have to be downloaded again, and they can even be re-installed offline if necessary. It also caches the resolved value for later use. If a package of the same version has already been resolved and downloaded, it doesn't need to go and fetch it again and get the updated download/resolved URL.
You can manually clear this cache with the following command.
npm cache clean --force
Alternately, it could be that difference in how different versions of NPM calculate the resolved field are to blame (following the Location header or not). However I think caching is more-likely to blame.

jspm install materialize but 404 on materialize.js when it runs

I am getting a 404 error on this on this get:
http://localhost:9000/jspm_packages/github/Dogfalo/materialize#0.96.1.js
I have used jspm to install materialize, and it the package is there as expected.
However, there is no actual file named materialize#0.96.1.js in the Dogfalo directory.
Is there something else I should be doing to get this to work?
Turn out that the structure of the materialize#0.96.1 is not fully consistent and indeed missing materialize#0.96.1.js file in the package base folder. Possible solution is to use next minor version materialize#0.97.0 which has proper structure.
To get newer version run
jspm install materialize=github:Dogfalo/materialize#0.97.0

lodash npm distribution in browser

I'm using lodash in my tests, Not using webpack or browserify (don't need to).
I found that the default npm build differs from what's in bower. I could of course use bower version, but I'm curious if I can use npm's instead (it's already there for Gulp).
For bower I could just add this line to karma.conf:
bower_components/lodash/lodash.js
but in default npm distro there's no lodash.js. Of course I can always build whatever version I want using lodash cli. But maybe there's even easier way, say maybe I need to add more than just one file from node_modules/lodash?
I think you are looking for node_modules/lodash/index.js