1 var path = require('path'),
3 f = require('util').format,
4 resolveFrom = require('resolve-from'),
5 semver = require('semver');
7 var exists = fs.existsSync || path.existsSync;
9 var find_package_json = function(location) {
13 if (exists(location + '/package.json')) {
15 } else if (location !== '/') {
16 location = path.dirname(location);
25 var require_optional = function(name, options) {
26 options = options || {};
27 options.strict = typeof options.strict == 'boolean' ? options.strict : true;
30 var location = __dirname;
31 // Check if we have a parent
33 location = module.parent.filename;
36 // Locate this module's package.json file
37 var location = find_package_json(location);
39 throw new Error('package.json can not be located');
42 // Read the package.json file
43 var object = JSON.parse(fs.readFileSync(f('%s/package.json', location)));
44 // Is the name defined by interal file references
45 var parts = name.split(/\//);
47 // Optional dependencies exist
48 if(!object.peerOptionalDependencies) {
49 throw new Error(f('no optional dependency [%s] defined in peerOptionalDependencies in package.json', parts[0]));
50 } else if(object.peerOptionalDependencies && !object.peerOptionalDependencies[parts[0]]) {
51 throw new Error(f('no optional dependency [%s] defined in peerOptionalDependencies in package.json', parts[0]));
54 // Unpack the expected version
55 var expectedVersions = object.peerOptionalDependencies[parts[0]];
56 // The resolved package
57 var moduleEntry = undefined;
59 var moduleEntryFile = name;
62 // Validate if it's possible to read the module
63 moduleEntry = require(moduleEntryFile);
65 // Attempt to resolve in top level package
67 // Get the module entry file
68 moduleEntryFile = resolveFrom(process.cwd(), name);
69 if(moduleEntryFile == null) return undefined;
70 // Attempt to resolve the module
71 moduleEntry = require(moduleEntryFile);
73 if(err.code === 'MODULE_NOT_FOUND') return undefined;
77 // Resolve the location of the module's package.json file
78 var location = find_package_json(require.resolve(moduleEntryFile));
80 throw new Error('package.json can not be located');
83 // Read the module file
84 var dependentOnModule = JSON.parse(fs.readFileSync(f('%s/package.json', location)));
86 var version = dependentOnModule.version;
87 // Validate if the found module satisfies the version id
88 if(semver.satisfies(version, expectedVersions) == false
90 var error = new Error(f('optional dependency [%s] found but version [%s] did not satisfy constraint [%s]', parts[0], version, expectedVersions));
91 error.code = 'OPTIONAL_MODULE_NOT_FOUND';
95 // Satifies the module requirement
99 require_optional.exists = function(name) {
101 var m = require_optional(name);
102 if(m === undefined) return false;
109 module.exports = require_optional;