codependency
Advanced tools
Comparing version 0.1.2 to 0.1.3
127
index.js
@@ -8,2 +8,47 @@ var dirname = require('path').dirname; | ||
/** | ||
* Resolves a peer dependency | ||
* | ||
* @param {Object} deps A hash-map of all known peer-dependencies. | ||
* @param {Module} baseMod The middleware module from where we resolve. | ||
* @param {string} name The name of the peer dependency to resolve. | ||
* @returns {Object} Information about the peer dependency. | ||
*/ | ||
function realResolve(deps, baseMod, name) { | ||
var range = deps[name]; | ||
var resolved = { | ||
supportedRange: range || null, | ||
installedVersion: null, | ||
isValid: null, | ||
isInstalled: null, | ||
pkgPath: pathJoin(name, 'package.json') | ||
}; | ||
var pkg; | ||
try { | ||
pkg = baseMod.require(resolved.pkgPath); | ||
resolved.isInstalled = true; | ||
if (typeof pkg.version === 'string') { | ||
resolved.installedVersion = pkg.version; | ||
if (range) { | ||
resolved.isValid = semver.satisfies(resolved.installedVersion, range); | ||
} else { | ||
resolved.isValid = true; | ||
} | ||
} | ||
} catch (error) { | ||
resolved.isInstalled = (error.code !== 'MODULE_NOT_FOUND'); | ||
resolved.isValid = false; | ||
} | ||
return resolved; | ||
} | ||
/** | ||
* This does the peer-requiring work. | ||
@@ -22,52 +67,54 @@ * | ||
function realRequire(deps, baseMod, middlewareName, name, options) { | ||
var range = deps[name]; | ||
var mod; | ||
options = options || {}; | ||
// defaults: | ||
var resolved = realResolve(deps, baseMod, name); | ||
var isInstalled = resolved.isInstalled; | ||
var range = resolved.supportedRange || '*'; | ||
options = options || {}; | ||
var mod; | ||
try { | ||
mod = baseMod.require(name); | ||
} catch (error) { | ||
// deal with non-existence | ||
if (isInstalled) { | ||
try { | ||
mod = baseMod.require(name); | ||
} catch (error) { | ||
if (error.code === 'MODULE_NOT_FOUND') { | ||
isInstalled = false; | ||
} else { | ||
// there was an error in the module itself | ||
// rethrow it if allowed. | ||
if (error.code === 'MODULE_NOT_FOUND') { | ||
if (options.optional) { | ||
return; | ||
} | ||
if (options.dontThrow) { | ||
return; | ||
} | ||
var cmd = 'npm install ' + name; | ||
if (range && range !== '*') { | ||
cmd += "@'" + range + "'"; | ||
throw error; | ||
} | ||
} | ||
} | ||
cmd += ' --save'; | ||
throw new Error( | ||
'Module "' + name + '" required by "' + middlewareName + '" not found. ' + | ||
'Please run: ' + cmd | ||
); | ||
if (!isInstalled) { | ||
if (options.optional) { | ||
return; | ||
} | ||
// there was an error in the module itself | ||
// rethrow it if allowed. | ||
var cmd = 'npm install ' + name; | ||
if (options.dontThrow) { | ||
return; | ||
if (range !== '*') { | ||
cmd += "@'" + range + "'"; | ||
} | ||
throw error; | ||
cmd += ' --save'; | ||
throw new Error( | ||
'Module "' + name + '" required by "' + middlewareName + '" not found. ' + | ||
'Please run: ' + cmd | ||
); | ||
} | ||
if (!range) { | ||
// no restriction | ||
if (range === '*') { | ||
// no restriction on version | ||
return mod; | ||
} | ||
var pkgPath = pathJoin(name, 'package.json'); | ||
var pkg = baseMod.require(pkgPath); | ||
if (!pkg.version) { | ||
if (!resolved.installedVersion) { | ||
if (options.dontThrow) { | ||
@@ -79,7 +126,7 @@ return; | ||
'Module "' + name + '" required by "' + middlewareName + '" has no version ' + | ||
'information in "' + pkgPath + '".' | ||
'information in "' + resolved.pkgPath + '".' | ||
); | ||
} | ||
if (typeof pkg.version !== 'string') { | ||
if (typeof resolved.installedVersion !== 'string') { | ||
if (options.dontThrow) { | ||
@@ -91,7 +138,7 @@ return; | ||
'Version of module "' + name + '" required by "' + middlewareName + '" is not a ' + | ||
'string (found instead: ' + (typeof pkg.version) + ').' | ||
'string (found instead: ' + (typeof resolved.installedVersion) + ').' | ||
); | ||
} | ||
if (!semver.satisfies(pkg.version, range)) { | ||
if (!resolved.isValid) { | ||
if (options.dontThrow) { | ||
@@ -102,3 +149,3 @@ return; | ||
throw new Error( | ||
'Version "' + pkg.version + '" of module "' + name + '" required by ' + | ||
'Version "' + resolved.installedVersion + '" of module "' + name + '" required by ' + | ||
'"' + middlewareName + '" does not satisfy required range "' + range + '".' | ||
@@ -243,2 +290,6 @@ ); | ||
requirePeer.resolve = function (name) { | ||
return realResolve(deps, baseModule, name); | ||
}; | ||
middlewares[middlewareName] = requirePeer; | ||
@@ -245,0 +296,0 @@ |
{ | ||
"name": "codependency", | ||
"keywords": ["peer", "dependency", "dependencies", "require", "module", "semver"], | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "Optional peer dependencies", | ||
@@ -6,0 +6,0 @@ "main": "index.js", |
@@ -97,2 +97,26 @@ # Optional Peer Dependencies for Node.js middleware | ||
It also has a resolve method which can give you information about a peer dependency before requiring | ||
it. | ||
**requirePeer.resolve(name)** | ||
The `name` argument is the name of one of your peer dependencies. The returned object has the | ||
following signature: | ||
```json | ||
{ | ||
"supportedRange": "2.5.1", | ||
"installedVersion": "2.5.1", | ||
"isInstalled": true, | ||
"isValid": true, | ||
"pkgPath": "zmq/package.json" | ||
} | ||
``` | ||
* `supportedRange` is the range that the middleware explicitly supports. | ||
* `installedVersion` is the version that is currently installed (null if none). | ||
* `isInstalled` indicates if the dependency has been installed. | ||
* `isValid` indicates if the installed version is valid within the supported range. | ||
* `pkgPath` is a path to package.json of the dependency, used internally by `requirePeer()`. | ||
## Errors | ||
@@ -99,0 +123,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18723
230
130