npm install -g npm-cross-link
You maintain many distinct npm packages and prefer to cross link them across each other, handling such setup manually can be time taking and error-prone.
npm-cross-link
is packages installer which installs dependencies into node_modules
the following way:
- Dependencies which expect to rely on some peer dependencies, are placed directly in
node_modules
- All other dependencies are linked:
- Maintained dependencies referenced by latest versions are linked to its corresponding repository folders
- All others are installed once in dedicated cache folder, and are linked into that folder
Within configuration you choose a folder (defaults to ~/npm-packages
) where maintained packages are placed, and predefine (at packagesMeta
) a package name to repository url mappings of packages you maintain.
When running npm-cross-link -g <package-name>
for maintained package, or when installing a maintained package as a dependency, following steps are pursued:
-
If package repository is not setup, it is cloned into corresponding folder (
~/npm-packages/<package-name>
by default). Otherwise optionally new changes from remote can be pulled (--pull
) and committed changes pushed (--push
) -
All maintained project dependencies (also
devDependencies
and eventualoptionalDependencies
) are installed/updated according to same flow.- Not maintained dependencies (not found in
packagesMeta
) are ensured to be installed in cache and linked (unless they depend on some peer dependencies, then they're copied directly intonode_modules
) - Maintained project dependencies (those found in
packagesMeta
) if referenced version matches local, are simply cross linked, otherwise they're linked from cache folder
- Not maintained dependencies (not found in
All important events and findings are communicated via logs (level of output can be fine tuned via LOG_LEVEL env setting).
As each dependency is installed individually (and maintained packages are being installed recursively), the first install may appear slower from regularnpm
or yarn
installs. Still it doesn't affect all further installs.
Internally npm-cross-link
relies on npm
being accesible to prepare cached versions of installed packages.
All subdependencies of project dependencies are installed within dependencies node_modules
folders. It means that if e.g. dependency A
and dependency B
, depend on same version of dependency C
, (and they're not maintained packages, so they're either linked to cache or installed on spot) they will use different installations of C
.
npm since early days ensured that in such scenarios C
is installed top level (so it's shared among A
and B
), npm-cross-link doesn't ensure that.
This shouldn't be a problem for most of packages. Still there are some packages for which having duplicate instances in environment may turn breaking or come with side effects, and as there's no practice being promoted to handle such scenarios, it's rare for those packages to come with any recovery logic.
Installs or updates all project dependencies.
Installs or updates given project dependencies. If dependency version is not specified then one from package.json
or latest is assumed.
Installs or updates given packages on its own. If it's maintained package, then it's ensured in resolved maintained folder, in all other cases packages is simply ensured to be installed in cache
Updates all are already installed maintained packages
--pull
- Pull eventual new updates from remote--push
- For all updated packages push eventually committed changes to remote--bump-deps
- (only non-global installations) Bump version ranges of dependencies inpackage.json
--no-save
- (only for dependencies install) Do not save dependency topackage.json
(effective only if its not there yet)--dev
- (only for dependencies install) Force to store updated version indevDependencies
section--optional
- (only for dependencies install) Force to store updated version inoptionalDependencies
section--prod
- (only for dependencies install) Force to store updated version independencies
section
User configuration is mandatory and is expected to be placed at ~/.npm-cross-link
path.
(Example of working configuration can be found at: medikoo/.npm-cross-link)
It's expected to be a typical Node.js module, that exposes (asynchronously if needed) a configuration object with following properties:
Optional (defaults to ~/npm-packages
). Folder at which maintained packages should be placed
Required. Meta data of each maintained package. Example form:
{
"packagesMeta": {
"es6-symbol": { "repoUrl": "git@github.com:medikoo/es6-symbol.git" },
"memoizee": { "repoUrl": "git@github.com:medikoo/memoizee.git" }
}
}
Supported package meta properties:
URL to git repository
If package is maintaned not at main
branch, provide branch name
Name of mutli package repository, that this package is part of.
If used together with multiRepoName
, then relative path in context of this repository.
Otherwise, can be set to customize package location (when relying on default ${packagesPath}/${package.name}
is not intended for some reason)
Meta data of eventual multi package repositories referenced in packagesMeta
.
Both repoUrl
and path
are mandatory
{
"multiPackageReposMeta": {
"multiRepoName": {
"repoUrl": "git@github.com:medikoo/multi-repo.git",
"path": "/Users/foo/multi-repos/multi-repoName"
}
}
}
Additionally branch
can be set, if it's not master
branch that should be treated as default
Optional. List of eventual hooks
Additional operation that should be done after successful package installation (it's run only for maintained packages).
Function is run with following arguments:
packageContext
- All needed information about package that was just installed or updateduserConfiguration
- User configuration as resolved and normalized from~/.npm-cross-link
inputOptions
- CLI command options
Optional. Eventual list of extra (not listed in package.json
) packages that should not be cleaned up from package node_modules
folder.
Installer by default removes all dependencies not referenced in package package.json
. Throught this option we may ensure that if we install something externally or via afterPackageInstall
hook, it remains untouched.
Optional. Eventual list of non maintained dependencies that in all cases should be copied into node_modules
and not linked to cache