npm install from Git in a specific version - node.js

Assumed that I have written a module for Node.js which I would like to keep private. I know that I can (should) add the line:
"private": "true"
to the package.json file, and I also know that I can npm install this module using a file system path or a link to a git repository, including GitHub.
I also know that I can put such a file system path or a link to a git repo into package.json, so that the dependencies part may look somewhat like this:
"dependencies": {
"myprivatemodule": "git#github.com:..."
}
What I now want is not to link to the latest version, but to a specific one. The only possibility I know of is to link to a specific commit using its ID. But this is way less readable and worse maintainable than using a version number such as 0.3.1.
So my question is: Is it possible to specify such a version number anyway and make npm search the git repository for the latest commit that includes this version?
If not, how do you resolve this issue in your projects? Do you live with commit IDs or is there a better solution to this?

The accepted answer did not work for me.
Here's what I'm doing to pull a package from github:
npm install --save "git://github.com/username/package.git#commit"
Or adding it manually on package.json:
"dependencies": {
"package": "git://github.com/username/package.git#commit"
}
Here's the full npm documentation:
https://docs.npmjs.com/cli/v9/configuring-npm/package-json?v=true#git-urls-as-dependencies

A dependency has to be available from the registry to be installed just by specifying a version descriptor.
You can certainly create and use your own registry instead of registry.npmjs.org if your projects shouldn't be shared publicly.
But, if it's not in a registry, it'll have to be referenced by URL or Git URL. To specify a version with a Git URL, include an appropriate <commit-ish>, such as a tag, at the end as a URL fragment.
Example, for a tag named 0.3.1:
"dependencies": {
"myprivatemodule": "git#github.com:...#0.3.1"
}
Note: The above snippet shows the base URL the same as it was posted in the question.
The snipped portion (...) should be filled in:
"myprivatemodule": "git#github.com:{owner}/{project}.git#0.3.1"
And, a different address format will be needed when SSH access isn't available:
"myprivatemodule": "git://github.com/{owner}/{project}.git#0.3.1"
Depending on your OS, you may also be able to link to the dependency in another folder where you have it cloned from Github.

If by version you mean a tag or a release, then github provides download links for those. For example, if I want to install fetch version 0.3.2 (it is not available on npm), then I add to my package.json under dependencies:
"fetch": "https://github.com/github/fetch/archive/v0.3.2.tar.gz",
The only disadvantage when compared with the commit hash approach is that a hash is guaranteed not to represent changed code, whereas a tag could be replaced. Thankfully this rarely happens.
Update:
These days the approach I use is the compact notation for a GitHub served dependency:
"dependencies": {
"package": "github:username/package#commit"
}
Where commit can be anything commitish, like a tag. In the case of GitHub you can even drop the initial github: since it's the default.

This command installs npm package username/package from specific git commit:
npm install https://github.com/username/package#3d0a21cc
Here 3d0a21cc is first 8 characters of commit hash.

My example comment to #qubyte above got chopped, so here's something that's easier to read...
The method #surjikal described above works for branch commits, but it didn't work for a tree commit I was trying include.
The archive mode also works for commits. For example, fetch # a2fbf83
npm:
npm install https://github.com/github/fetch/archive/a2fbf834773b8dc20eef83bb53d081863d3fc87f.tar.gz
yarn:
yarn add https://github.com/github/fetch/archive/a2fbf834773b8dc20eef83bb53d081863d3fc87f.tar.gz
format:
https://github.com/<owner>/<repo>/archive/<commit-id>.tar.gz
Here's the tree commit that required the /archive/ mode:
yarn add https://github.com/vuejs/vuex/archive/c3626f779b8ea902789dd1c4417cb7d7ef09b557.tar.gz
for the related vuex commit

I needed to run two versions of tfjs-core and found that both needed to be built after being installed.
package.json:
"dependencies": {
"tfjs-core-0.14.3": "git://github.com/tensorflow/tfjs-core#bb0a830b3bda1461327f083ceb3f889117209db2",
"tfjs-core-1.1.0": "git://github.com/tensorflow/tfjs-core#220660ed8b9a252f9d0847a4f4e3c76ba5188669"
}
Then:
cd node_modules/tfjs-core-0.14.3 && yarn install && yarn build-npm && cd ../../
cd node_modules/tfjs-core-1.1.0 && yarn install && yarn build-npm && cd ../../
And finally, to use the libraries:
import * as tf0143 from '../node_modules/tfjs-core-0.14.3/dist/tf-core.min.js';
import * as tf110 from '../node_modules/tfjs-core-1.1.0/dist/tf-core.min.js';
This worked great but is most certainly #hoodrat

I describe here a problem that I faced when run npm install - the package does not appear in node_modules.
The issue was that the name value in package.json of installed package was different than the name of imported package (key in package.json of my project).
So if your installed project name is some-package (name value in its package.json) then
in package.json of your project write: "some-package": "owner/some-repo#tag".

If you're doing this with more than one module and want to have more control over versions, you should look into having your own private npm registry.
This way you can npm publish your modules to your private npm registry and use package.json entries the same way you would for public modules.
https://docs.npmjs.com/files/package.json#dependencies

Related

NPM how to install package as it was another

want to install package com.cordova.plugin.cache and its content i need it to be also as cordova-plugin-cache..
Example package.json was like this:
"dependencies": {
// Note these two are the same but with different name
"cordova-plugin-cache": "git+git#gitlab.com:dev/library/org.git",
"com.cordova.plugin.cache": "git+git#gitlab.com:dev/library/org.git"
}
But i published a modified version both of it on a private npm repository to remove the dependency as a repository.
"dependencies": {
// Note these two are the same but with different package name
"cordova-plugin-cache": "git+git#gitlab.com:dev/library/org.git",
"com.cordova.plugin.cache": "git+git#gitlab.com:dev/library/org.git"
}
Is this even possible? do i have to save both packages as they were two different?
Actually i have one package in a private npm registry, but don't want to duplicate the project.
Any hint is appretiated.
NPM itself has no such feature, it was discussed on their GitHub repository here and it was decided not to implement such a feature.
The solution outlined in this article may prove to solve your problem:
You can utilise the link-module-alias module, add a _moduleAliases section to your package.json that describes the alias you wish to establish and then add a postinstall script that executes the aforementioned module.

npm: install dependency from local file when available, otherwise from github

I am developing a package (library) at the same time as the application that uses it (also a package) and I would like to use the local library if available as sibling of the application, and otherwise download the latest release from github.
I tried having two references in dependencies and optionalDependencies, hoping that a failure of the latter would still use the specification in the former, but that doesn't work. The package is skipped.
Is this possible at all? Or maybe there are other ways to solve the problem? Maybe some creative use of the script hooks?
Maybe what you can do is to publish it on GitHub and in your package.json you can call directly from the repository something like this:
"dependencies": {
"mongoose-cipher": "git+ssh://git#github.com:estrada9166/mongoose-
cipher.git"
}
or
"dependencies": {
"mongoose-cipher": "git+https://git#github.com:estrada9166/mongoose-
cipher.git"
}
also you can specify the release, in case your repository has one, something like:
"dependencies": {
"mongoose-cipher": "git+ssh://git#github.com:estrada9166/mongoose-
cipher.git#v0.0.7"
}
you can create a private repository with your package and by this way it is safe!
To install from GitHub: npm install <git repo url>
also you can add your package on the node_modules folder and add the dependency on your package.json but personally I prefer to publish to GitHub and install it on my project, is easier.

How to use fork version of npm package in a project

Let's say there is an npm package called abcd.
Normally in package.json, we specified the dependencies as
"abcd": "^1.0.0",
But this abcd does not work as expected, so I forked (and modified) it inside https://github.com/mygithubid/abcd
Then I run npm install git+https://git#github.com/mygithubid/abcd.git and in package.json, the definition is changed to
"abcd": "git+https://github.com/mygithubid/abcd.git",
After restarting the project that using this abcd, now it throws error
Module not found: Can't resolve 'abcd'
... even though I saw the abcd folder is added inside node_modules
Could you advise the mistake I made in above? Thanks!
One fairly clean option is to use patch-package:
https://www.npmjs.com/package/patch-package
If the people using your project might use either npm or yarn, then remeber to make the patch available for both. More info under patch-package --use-yarn.
Patch or fork? See https://www.npmjs.com/package/patch-package#benefits-of-patching-over-forking
Be sure that the github repository contains compiled files, at most cases you need build the package for npm first, the compiled files push only to NPM.
To find out how to build the package check the package.json file

Can I override the url npm pulls a package from?

I have a legacy project which depends on a specific version of an npm package which through a dependency chain depends on a specific npm package of phantomjs, the binaries of which are no longer online at the registered location. This breaks the project's build.
Updating package versions is not an option.
I can fool npm by manually fetching the required version of phantomjs and dropping it into my system's download folder, but this is a workaround, I want a cleaner fix, ideally something that sits in a config script.
Can I, in my project's package.json or .npmrc files, force npm to use another url for a package # some version, every time "npm install" is run for that project?
A possible solution is uploading the package to github and proceed as in NPM docs https://docs.npmjs.com/files/package.json#urls-as-dependencies
I figured out that this is possible using npm-shrinkwrap (https://docs.npmjs.com/files/package-locks). Basically, you add an npm-shrinkwrap.json file to your project, alongside package.json. In the shrinkwrap file, you can override any specific package listed in package.json - anywhere in that package's dependency chain, you specify a URL to fetch a dependency package from.
{
"name": "MyProject",
"dependencies": {
"A" : {
"version" :"1.2.1",
"dependencies": {
"B": {
"version": "https://myBForkUrl.git"
}
}
}
}
If MyProject depeneds on package A, which in turn depends on B, but B is unmaintained and has a critical bug, I can roll my own fork of B, fix the bug and host it at https://myBForkUrl.git, without also having to fork A. Based on NPM's documentation it looks like this overriding can be nested as deep as necessary.

Shipping node.js project with custom dependencies

I fixed a couple of issues in nested dependencies of my node.js project (dependencies are managed by npm). These fixes are pending pull requests and thus aren't published. What's the best way to use them in my project?
I know that I can do npm link inside the fixed version of the library and then npm link library-name inside my project to force npm to use my fixed version. This approach works but installs my library-name globally on my machine which I don't like.
Is it possible to have it locally in main project's repo, force the project to use it and don't do npm link.
You can use a url as the dependency and point it to your own repo (fork).
https://docs.npmjs.com/files/package.json#urls-as-dependencies
for example:
"dependencies": {
"foo": "git+ssh://user#hostname:project.git#commit-ish"
}
If your pull requests are on GitHub its even easier...
As of version 1.1.65, you can refer to GitHub urls as just "foo":
"user/foo-project". Just as with git URLs, a commit-ish suffix can be
included.
https://docs.npmjs.com/files/package.json#github-urls

Resources