Can "NPM -i" (local) install a global package without i know it? - npm

I'm ok with local dependencies that packages install. But now I have a huge concerns about if a local installed package can install other global packages as dependencies.
as example:
npm install nunjucks
npm install sqlite
or
npm install botkit

It is not possible to mark a dependency as global in package.json, so that it is installed system-wide when you run npm i.
Here's an old comment by Isaac Schlueter stating that this will never be implemented.
Hooowever, it would be really simple to write a preinstall script to install arbitary dependencies globally.
{
"name": "Project",
"version": "1.0.0",
"description": "Preinstall script to install global deps",
"main": "index.js",
"scripts": {
"preinstall": "node -e \"const {execSync} = require('child_process'); JSON.parse(fs.readFileSync('package.json')).globalDependencies.forEach(globalDep => execSync('npm i -g ' + globalDep));\""
},
"dependencies": {
"react": "16.13.1"
},
"globalDependencies": [
"lodash"
],
"license": "ISC"
}
Copy this code into a package.json file in a folder on your PC. Then, in the folder run npm i. It will install React locally (in a node_modules folder) and it will install lodash globally.
You can verify this using: npm i ls -g --depth=0.
Reference: Install dependencies globally and locally using package.json
As to your question:
Can npm -i (local) install a global package without me knowing it?
It's not entirely silent. When running npm i for the above package.json file, you would see the following output:
> Project#1.0.0 preinstall /home/jim/Desktop/Project
> node -e "const {execSync} = require('child_process'); JSON.parse(fs.readFileSync('package.json')).globalDependencies.forEach(globalDep => execSync('npm i -g ' + globalDep));"
npm WARN Project#1.0.0 No repository field.
audited 6 packages in 1.113s
found 0 vulnerabilities
But whether you would catch this when running npm i on a large project is debatable.

Related

Why does jsonlines package get resolved to registry.npm.taobao.org?

When I install the npm package jsonlines, it gets resolved to a mirrored registry registry.npm.taobao.org rather than registry.npmjs.org. It only does this for jsonlines. What causes this?
Here's the diff on my package-lock.json. The original "resolved" value was created when another developer installed the package:
"jsonlines": {
"version": "0.1.1",
- "resolved": "https://registry.npmjs.org/jsonlines/-/jsonlines-0.1.1.tgz",
+ "resolved": "https://registry.npm.taobao.org/jsonlines/download/jsonlines-0.1.1.tgz",
"integrity": "sha1-T80kbcXQ44aRkHxEqwAveC0dlMw="
},
I confirmed my configured registry is npmjs.org:
$ npm config get registry
https://registry.npmjs.org/
The developer's npm registry was likely set to registry.npm.taobao.org when they ran npm install jsonlines. Some users have npm configured to use the taobao registry for geographic proximity.
Deleting node_modules and package-lock.json and re-running npm install fixes it.
Tip: Use lockfile-lint to prevent it from happening again.
npm install --save-dev lockfile-lint
Run lockfile-lint to your lint script, ideally in a pre-push git hook.
Add this config to your package.json:
"lockfile-lint": {
"allowed-schemes": [
"https:"
],
"allowed-hosts": [
"npm"
],
"empty-hostname": false,
"type": "npm ",
"path": "package-lock.json"
},

Why is npm installing packages from private registry and not from registry.npmjs.org

I have create a .nmprc file in my project directory as:
#mycompany:registry=https://registry.mycompany.com/
However when I do npm install I see package dependencies which do not start with #mycompany also gets installed from https://registry.mycompany.com/ and not from https://registry.npmjs.org/.
This is what I see in package-lock.json:
"yaml": {
"version": "1.7.2",
"resolved": "https://registry.mycompany.com/yaml/-/yaml-1.7.2.tgz",
"integrity": "sha512-qXROVp90sb83XtAoqE8bP9RwAkTTZbugRUTm5YeFCBfNRPEp2YzTeqWiz7m5OORHzEvrA/qcGS8hp/E+MMROYw==",
"dev": true,
"requires": {
"#babel/runtime": "^7.6.3"
}
Since you're using an .npmrc File, the command npm install will try to find all packages in your companies registry https://registry.mycompany.com/
If you want to install all the other Packages you need to update your .npmrc File as followed.
Your Current .npmrc File:
#mycompany:registry=https://registry.mycompany.com/
Updated Version
#mycompany:registry=https://registry.mycompany.com/
registry=https://registry.npmjs.org
If you run npm install it will install all Packages with the #mycompany FLag from your companies Registry and it will try to install all other packages from the public npm Registry.

How to install local NPM module and it's dependencies to project?

I'm working on shareable eslint configuration to spread automation and internal best-practices. So I'm adding some eslint plugins and tools as dependencies.
Context
Env
$ node --version;
v8.2.1
$ npm --version
5.3.0
Local package
To do so I created a local npm project, says eslint-config-company, with the following package.json:
{
"name": "eslint-config-company",
"version": "0.0.1",
"main": "index.js",
"dependencies": {
"eslint": "4.x.x",
"eslint-plugin-ember-suave": "1.x.x",
"eslint-plugin-prettier": "2.x.x",
"prettier": "1.x.x"
},
"files": [
"index.js"
],
"keywords": [
"eslint",
"eslintconfig"
],
"repository": "company/eslint-config-company",
"private": true
}
and files:
index.js package.json README.md yarn.lock
Installing
Then, I install my eslint-config-company package into a another project to test it:
npm install --save-dev --verbose ../eslint-config-company
In node_modules/ directory I got the eslint-config-company/ as a symlink:
$ ls node_modules/eslint-config-company -lah
lrwxrwxrwx 1 me me 29 Aug 17 22:02 node_modules/eslint-config-company -> ../../eslint-config-company/
but no trace of either prettier nor eslint-plugin-prettier
$ ls node_modules/{prettier,eslint-plugin-prettier}
ls: cannot access 'node_modules/prettier': No such file or directory
ls: cannot access 'node_modules/eslint-plugin-prettier': No such file or directory
N.B.: eslint and eslint-plugin-ember-suave are already dependencies of that project thus exists.
Question
Am I wrong assuming that my package's dependencies will install on npm install ?
How do I fix my package in order to install them?
related: issue on npm/npm
The eslint-config-company's dependencies are held in that module's node_modules folder - so it will be able to find the code it needs via the symlink (assuming npm install has been run on the eslint-config-company module folder).
When packaged up - the node_module folder is included as well, so it translates up to delivery time as well.
Create global module of your project eslint-config-company (in this module folder):
npm link
and links the global installation target in another project whit :
npm link eslint-config-company
source : https://docs.npmjs.com/cli/link

npm install dependencies of local modules

I'm having trouble using npm with a local module. My project's structure looks like:
package.json
local_module/
- package.json
- gulpfile.json
gulpfile.js
The main project's package.json is essentially:
{
"dependencies": {
"local_module": "file:local_module"
},
"devDependencies": {
"gulp": "..."
}
}
The local module's package.json is essentially:
{
"scripts": {
"prepublish": "gulp release"
},
"devDependencies": {
"gulp": "..."
}
}
My intention is keep my project modular by keeping local_module as its own package that is used as a dependency for the main project. I want to run npm install in the main project and use local_module from node_modules. However, local_module needs gulp installed to run the prepublish step, and when running npm install from the main project, it does not install the dependencies for local_module, and so gulp isn't installed, so it can't do the prepublish step.
Several questions like this have been asked, like NPM doesn't install module dependencies, but many are old and there are so many versions of npm that I can't get a clear solution.
How can I get npm to install local_module's dependencies before the prepublish step? I tried adding a preinstall step for the main project, e.g.
"preinstall": "cd local_module && npm install"
But it seems npm tries to run the prepublish step of local_module before running the preinstall for the main project. I want a solution that will do this in one npm install step rather than having a separate step before this to do npm install in the local module.
I have found a solution that will work for me in the immediate future. I changed local_module's package.json to:
{
"scripts": {
"prepublish": "npm install --ignore-scripts && gulp release"
},
"devDependencies": {
"gulp": "..."
}
}
When npm install is run from the main project, the prepublish step is run first in local_module, so I force prepublish to also do an install so that gulp is available to do the actual prepublish step. This is hardly ideal however.

Custom paths for package managers like Nuget/npm/bower/typings

I'm setting up a project in Visual Studio based on AngularJS and Typescript and it's a bit discouraging that I have to deal with yet another package manager as soon as I need to install dependencies.
The issue I have is that package managers require files containing dependencies to be located in a particular place.
Let's take npm for example.
I place packages.json at ./SolutionDirectory/MyApp.Web/
But when I run npm install, I just get ENOENT: No such file or directory. because cwd is ./SolutionDirectory
It works fine if I'm doing cd ./SolutionDirectory/MyApp.Web and run npm install after that.
For bower I was able to handle similar issue by just passing additional arguments like:
bower install --config.cwd=./SolutionDirectory/MyApp.Web/app/lib --config.directory=vendor
This command just gets bower.json from ./SolutionDirectory/MyApp.Web/app/lib and installs packages to ./SolutionDirectory/MyApp.Web/app/lib/vendor
Is there a way to have same thing to pass packages.json location to npm before it installs?
Is there a way to pass typings.json location to typings before it installs? to pass target directory location for typings installed?
Is the same doable for Nuget?
For npm:
npm install <folder>
<folder> is the path to the folder which contains the package.json file.
For typings:
typings install [<name>=]<location>
<location> is the path to the typings.json
For NuGet:
nuget install packageId|pathToPackagesConfig [options]
pathToPackagesConfig is the path to the packages.config file.
So, to answer the question, yes it's possible to specify a path to the config file's location for all of these package managers.
Is there a way to have same thing to pass packages.json location to npm before it installs?
No, there isn't. Currently there is no way to overwrite cwd value in npm. You should move directory and run it:
`$ cd SolutionDirectory/MyApp.Web/ && npm install`
Here is the similar discussion to this: https://github.com/npm/npm/pull/10958
Is there a way to pass typings.json location to typings before it installs? to pass target directory location for typings installed?
Technically yes, but I guess you'd like to just do typings install with typings.json. How about to put typings.json to the same path with package.json and use npm lifecycle script?
$ ls
package.json typings.json
$ cat package.json
{
"name": "name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"postinstall": "typings install"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"typings": "^0.7.12"
}
}
$ npm install
=> after npm install, typings install will start with typings.json
Is the same doable for Nuget?
Nuget is also package manager, so it should has similar features, like nuget mirror command can be npm config set registry and nuget locales can be npm cache I guess. Technically it's a different software, but I think understanding about both softwares is good way to know the concept and summary of each others.