Setup:
Package models
- Common mongoose models used across multiple apps
- peerDependencies: "mongoose"
Package app
- dependencies: "mongoose", "models"
- Linked with models through
app> npm link models
Issue:
When developing models
, I need mongoose installed under node_modules
, otherwise it can't find mongoose.
However, when using models
under app
, if mongoose exists under node_modules
in models
, it uses that copy instead of sharing the same instance of mongoose with app
.
The way I'm making this work now is installing mongoose when developing models
, then deleting it when using it under app
. I've looked into parent-require
but this seems to only solve the issue with npm link not finding the package from the parent, not the issue with having to remove/install the node_module (or am I doing this incorrectly?)
Related:
Sharing a Mongoose instance between multiple NPM packages
I've taken to using require.main.require
instead of require
for modules that need a shared instance.
For example, require.main.require('mongoose')
will guarantee only the top-level mongoose is used.
In case you get an error
require.main.require is not supported by webpack
... call npm link <required module>
in your module's root dir
E.g. I had the same issue with peerDependency react. So I did npm link reack
for my local module and it worked.
Here is a module that you can use that deals with parent and grandparent modules that are linked
/**
* the original module scope
*/
const _BASE_MODULE = module;
/**
* the top level module (fixes nasty peer dependency issues with npm link)
*/
const _MODULE = topLevelModule();
/**
* find topmost module scope
*/
function topLevelModule() {
let _mod = _BASE_MODULE;
while (_mod.parent) {
_mod = _mod.parent;
}
return _mod;
}
/**
* cheap way to check if the module is available,
*
* @param {string} mod module name
* @return {boolean}
* @todo if we need better then we should switch to browserifys resolve package, but thats heavy
*/
export function isAvailable(mod) {
try {
_MODULE.require.resolve(mod);
return true;
} catch (e) {
return false;
}
}
/**
* requires a module from the top level scope
* @param {string } mod module name
* @return {*}
*/
export function topLevelRequire(mod) {
return _MODULE.require(mod);
}