This is a simple set of scripts that is just intended to make it easy for someone to import an NPM package and all of its dependencies in a safe way.
In order to maintain some notion of a clean software environment, our organization maintains a private NPM registry that contains only assets that have been virus scanned and then uploaded. The process for downloading an internet NPM package with all of its dependencies, scanning them for viruses and then uploading them to the private registry is a bit onerous. To make it easier, a few scripts were developed that will be described below. The 3 primary scripts are:
- config-npmrc - a convenience script to setup your personal
.npmrc
file correctly - npm-importer - a link to the latest version of the
npm-importer
script that takes an npm package and version in the normal format and download it and all its dependencies to a quarantine location, scans them, and then publishes them to our local repo (if no viruses are found). - toa-ui-importer - this script is meant to grab a
package.json
file either directly or via an install package directory and grab all of its dependencies. This script uses thenpm-importer
script to iterate over all the dependencies downloading, quarantining, scanning and publishing them.
Each of these sripts has a 'help' message that can be accessed by either just executing the script with no arguments or by typing <script name> -h | --help
.
The sections below provide some additional insights into either how they work, why they work the way they do, and what you should know about what they do. There is a Future Improvements and Troubleshooting section at the end of this README.
This script sets up your personal .npmrc
file to either to either access the internet NPM registry, use our internal proxy to the internet, or use our private one. The remaining scripts in this README use a function
to perform the exact same outcome as this convenience script. This script can be copied to a user's personal tool path, such as $HOME/bin, and used independently of the remaining scripts. For a complete list of arguments, type config-npmrc --help
.
This script expects one commandline argument that specifies the 'mode' you want to set your .npmrc
up for. The list below describes the modes. In all cases, your 'prefix' is only altered if you use the --prefix
switch described in the "Switches and Flags" section, below.
- 'open' :: use the https://registry.npmjs.org/ registry and delete all proxy configurations. Your 'prefix' will be unaltered access our local one (the one that does not proxy the internet).
- 'proxy' :: use the internal 'npm-proxy' registry. There is little reason to use this registry. This proxy literally proxies requests to the https://registry.npmjs.org/ registry. It first tries to find the package, and all its dependencies, in the local registry and then fetches and caches them if it can't. While the local registry is occasionally virus scanned, this leaves a gap of time when the downloaded software is being used that its "hygiene" has not been validated.
- 'safe' :: use the internal 'npm-mpf' registry. This registry is not proxied and is supposed to represent all NPM modules that have been downloaded, scanned and then uploaded to the internal registry. Typing
config-npmrc "safe"
ensures that you are using a registry that is not accessing the internet.
In addition to '--help', '--debug' and '--prefix' are the only real flags.
--help
:: print the help or usage message and exit.--debug
:: collects all the output from debug level messages and bash / terminal commands and presents them as terminal output. By default, the script redirects all this output to/dev/null
.--prefix
:: This switch allows you to set the NPM prefix in your.npmrc
. When you typenpm install
, npm will, by default, create a localnode_modules
directory (in your$CWD
) and start installing your packages into it. If you usenpm install -g
, npm will install them into$prefix/lib/node_modules
. Once this prefix is set in your.npmrc
it will not be overriden in future calls to this script unless you use the--prefix
option again to set it to a new path orreset
it (delete the existing prefix in your.npmrc
file).
This script is intended to provide a convenience mechanism for a user to import, in a safe manner, an NPM module. The script will generally perform the following steps:
- switch your
.npmrc
configuration to access the https://registry.npmjs.org/ registry. - Create a quarantine location in which to download the requested NPM package and all of its dependencies. The user must have
write
access to the directory location and will be given the chance to remove or keep any existing files at that location. - Download the request package@version that the user requested. The _version' is not necessary.
- Make a full, and unique list of all dependencies that got downloaded with the package. When adding dependencies to the list, you will see either a red '*' or a green '+' indicating that the dependency is already in our list of packages that need to be imported, a red '*', or is being added newly, a green '+'.
- For each of the packages in the above list, the script will then check to see if the package and version are in our internal registry. If they are not, they will be virus scanned. If a virus is detected in any package, the package is skipped, a noticable error message is printed and a report detailing that a virus was detected for this package is produced; it will be displayed at the end of the script for further action.
- For all packages that are not in our internal registry and are not infected with a virus, we will publish the package and unique version to the registry. As a result of a quirk in NPM, sometimes our primary package, the one used on the commandline for this script, will request a version like '2.0.1'. While installing all the other dependencies, some other package may require a later version of that same package, in this case '3.0.0'. What will actually get published to our internal registry is the '3.0.0' version. This is annotated in the output status messages by a green version number at the end of the yellow "Publishing ..." message. See troubleshooting section at the end of this README for why this is a problem and how to fix it.
This script expects / requires only one commandline argument: the NPM package and, optionally, version that you want to safely import into our local registry. For example:
npm-importer color@>2.0.0
This will import the color
package that has any version greater than 2.0.0 with all of its dependencies.
All of these switches and flags are optional, but may be useful in either debugging a problem or fine tuning your use of this script for maximum efficiency.
-h|--help
:: print the help or usage message and exit.-d|--debug
:: collects all the output from debug level messages and bash / terminal commands and presents them as terminal output. By default, the script redirects all this output to/dev/null
.-c|--cwd
:: much like the--debug
switch, this switch controls the output from directory-based shell commands likepopd
,pushd
,pwd
, etc. Using this flag will cause all output from those commands to be echoed tostdout
. This flag is largely just for development debug and is not needed for any normal operation.--align
:: This is just an output formatting flag. It requires an integer argument and just sets an 'indent' of that many spaces at the beginning of every console output line.--dev
:: A switch that allows you to also download, scan and publish all development dependency packages like you would withnpm install
. By default, this script acts likenpm install --only=production -g
. This switch effectively causes anpm install --development
to be done in the main package; pulling in all its development dependencies and, consequently, their dependencies.--rebuild-quarantine
:: The default behavior for this script is to check if the default quarantine directory,/data/npm-quarantine
, exists. If it does, it will prompt the user to either reuse the directory and its contents or remove the existing directory and recreate it. This flag is a binary flag that automatically selects the 'force and recreate' mode. The quarantine directory location is not settable at this time via commandline switches and flags, but is easily settable by searching for^quarantine=
and replacing the/data/npm-quarantine
with whatever the user desires (or you could add a commandline flag if you are feeling industrious).--nocred
:: stands for 'no credentials'. When you first go tonpm publish
a module, your registry credentials may not be in your.npmrc
. As such, this script assumes you need to login initially and prompts you to supply user name, password, and an email address. If you know your credentials are already valid and don't want to type them in, use--nocred
and the script will skip the authentication stage. If you are wrong and have not previously authenticated, the publish step of the script will fail and you'll have to try again.
While slightly misleading, this script is primarily intended to import all the dependencies (and eventually the development dependencies) for the TOA web UI. It can generally be used to import all the dependencies listed in any module's package.json
file, but it was only tested on the TOA web UI.
Although the 'help' or 'usage' message makes it appear that you can only provide the package.json
file for which you are trying to import all the dependencies, you can also use the topmost directory of the module who's dependencies you are trying to satisfy. For instance, either the following commands will work:
toa-ui-importer --nocred $HOME/git/toa/toa-core/web
# or
cd $HOME/git/toa/toa-core/web # this is optional / for demonstration
toa-ui-importer --nocred package.json
All of these switches and flags are optional, but may be useful in either debugging a problem or fine tuning your use of this script for maximum efficiency.
-h|--help
:: print the help or usage message and exit.-d|--debug
:: collects all the output from debug level messages and bash / terminal commands and presents them as terminal output. By default, the script redirects all this output to/dev/null
.-c|--cwd
:: much like the--debug
switch, this switch controls the output from directory-based shell commands likepopd
,pushd
,pwd
, etc. Using this flag will cause all output from those commands to be echoed tostdout
. This flag is largely just for development debug and is not needed for any normal operation.--dev
:: A switch that allows you to also download, scan and publish all development dependency packages like you would withnpm install
. By default, this script acts likenpm install --only=production -g
. This switch effectively causes anpm install --development
to be done in the main package; pulling in all its development dependencies and, consequently, their dependencies. On thetoa-ui-importer
script, this switch is largely a pass through to thenpm-imporer
script.--nocred
:: stands for 'no credentials'. When you first go tonpm publish
a module, your registry credentials may not be in your.npmrc
. As such, this script assumes you need to login initially and prompts you to supply user name, password, and an email address. If you know your credentials are already valid and don't want to type them in, use--nocred
and the script will skip the authentication stage. If you are wrong and have not previously authenticated, the publish step of the script will fail and you'll have to try again. Note: if you are trying to import a lot of dependencies, like the TOA UI has, you will absolutely want to use this switch or you will be prompted to authenticate with the local registry for each dependency; very annoying! To authenticate once, just typeconfig-npmrc 'safe' && npm adduser
. It will prompt you for your credentials. Then use this--nocred
switch which will, in turn, be passed to thenpm-importer
script.
Don't forget about the --debug
flag on both the npm-importer
and
toa-ui-importer
scripts. The flag will show you the output that tne various
npm
commands are producing as well as track all the directory traversal that
the script is doing; which is very important to the way NPM works.
There are two possible reasons you are seeing this error message.
- If you haven't used
npm-importer
to import the package then, no surprise, its not there and you should usenpm-importer
to import it (That's why I spent all the time writing and documenting it). - If you get this error when trying to install some other package that you think you already imported, then you have probably run into the NPM dependency hell problem (affectionately named). When NPM installs the dependencies of a package, it installs them all in the
node_modules
directory of the parent package. For instance, if you typedtoa-ui-importer package.json
to import all its dependencies, they will all go in/data/npm-quarantine/lib/node_modules/toa-ui
. In addition, dependencies oftoa-ui's
dependencies will also get put in that same location, occasionally changing the version of the package that exists there. When we publish them to the local registry, we get whatever version exists at that time. It may not be the version that thetoa-ui package.json
file requires.
For case #1 above, just type npm-importer <package>@<version>
and then try installing whatever you tried when you got the error message.
For case #2 above, the remedy is acutally the same. Just type npm-importer <package>@<version>
and then try importing the toa-ui
(or whatever package) again. (I just wanted you to understand why you were getting the error) To date, I think there are about half a dozen packages that the toa-ui
requires that end up triggering this error. Since they've been imported (as of 03/19/2020) to our local registry, you should see it happen again until dependency versions or packages are updated for the TOA web UI.
This error most often occurs with "optional" dependencies. For whatever
reason, intalling a package with its development dependencies doesn't pick up
one of its dependencies. This happens, for instance with chokidar@^1.7.0
.
It always fails to pick up fsevents@^1.0.0
(in this case its becasue
fsevents
is intended for another os/arch). If you determine you need this
package, just try running:
# example from [email protected] install
npm-importer --nocred --rebuild-quarantine true --debug esprima@~1.0.2
Add documentationBetter than most so I'm calling this 'Done'!