Can I override the url npm pulls a package from? - node.js

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.

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 pack to include local modules

I have some local modules that I want to include in my package to be sent to a server. Since these local packages are not on the npm registry, they need to be part of the package.
I have tried some ways to get the node_modules folder included in the package using npm pack, however it seems this is not possible at all?
Secondly I tried to list the local modules in the bundledDepencies in the package.json file and use npm pack, however this also does not include the local modules, no matter what;
{
"name": "dev",
"version": "1.0.0",
"main": "main.js",
"dependencies": {
"local-module": "file:../../local-module"
},
"bundledDependencies": [
"local-module"
]
}
How can I get these local modules included in the dev package?
The local module does contain dependencies itself, not sure if that makes things more complicated?
I had a similar issue a while back, and a good and simple solution, is just to put your local modules into private git repos (which are now free on GitHub, thanks Microsoft 🙌)
Then, in your package.json, just add:
"dependencies" : {
"name1" : "git://github.com/user/project.git#commit-ish",
"name2" : "git://github.com/user/project.git#commit-ish"
}
Source, npm docs
I believe Alicia's approach is the cleanest one. However for someone that runs into the same issue as I did, whereby a server requires a tarball, but does not have git installed, I added my local packages to a seperate folder in the project called repo and referenced them in the package.json as;
"dependencies": {
"my-local-package": "file:./repo/my-local-package"
}
There's also yalc, which creates a local store for local packages. After adding a local package to the store, you can use yalc to copy the local package into another package. You can also use it to do updates of local packages.

How to prevent an unused npm dependency to be installed?

So in my project, I require multiple packages, including "dep1".
"dep1" requires another dependency, "dep2".
And "dep2" requires multiple packages, including "dep3".
The problem is, "dep3" is not compatible with the licence I want to use (well actually, with the licence my boss wants to use).
Fortunatly, only one function of "dep2" uses "dep3", and "dep1" does not use this function. So if I remove "dep3" from node_modules, all will go smoothly.
The problem I have is, how to modify package.json to take this into account when doing npm install, and not install this package ?
I am aware I could branch "dep2" to supress the function, and then "dep1" to use the modifies "dep2", but this seems overkill, and I would be dependant of the owner of the packages to accept my branch. I am looking for a solution like 'well, just add the line ignore : "dep3" into package.json', but can't find any.
Thanks for your help !
The obvious way is to remove unwanted dependency from node_modules in NPM postinstall hook.
Alternatively, a stub can be provided instead of dep3. A stub should contain package.json that will identify it as a substitute with matching version:
{
"name": "dep3",
"version": "VERSION THAT MATCHES DEP2 CONSTRAINT"
}
It can be specified as local dependency in dep:
...
"dependencies": {
"dep3": "./dep3-stub",
...
Or as Git dependency:
...
"dependencies": {
"dep3": "github-user-name/dep3-stub",
...
If version constraint matches, dep3 stub will be installed and used instead of real package, otherwise dep2 may install its own copy of dep3.
I am aware I could branch "dep2" to supress the function, and then "dep1" to use the modifies "dep2", but this seems overkill, and I would be dependant of the owner of the packages to accept my branch.
This is a reasonable approach. This is no concern to the owner. dep2 fork can be used instead of dep2 NPM package in the same way as shown for dep3.

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.

npm install from Git in a specific version

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

Resources