9754581ac9a03d590799f5e426a8ba04e9e6cd6e
[aai/esr-gui.git] /
1 var path = require('path'),
2   fs = require('fs'),
3   f = require('util').format,
4   resolveFrom = require('resolve-from'),
5   semver = require('semver');
6
7 var exists = fs.existsSync || path.existsSync;
8
9 var find_package_json = function(location) {
10   var found = false;
11
12   while(!found) {
13     if (exists(location + '/package.json')) {
14       found = location;
15     } else if (location !== '/') {
16       location = path.dirname(location);
17     } else {
18       return false;
19     }
20   }
21
22   return location;
23 }
24
25 var require_optional = function(name, options) {
26   options = options || {};
27   options.strict = typeof options.strict == 'boolean' ? options.strict : true;
28
29   // Current location
30   var location = __dirname;
31   // Check if we have a parent
32   if(module.parent) {
33     location = module.parent.filename;
34   }
35
36   // Locate this module's package.json file
37   var location = find_package_json(location);
38   if(!location) {
39     throw new Error('package.json can not be located');
40   }
41
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(/\//);
46
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]));
52   }
53
54   // Unpack the expected version
55   var expectedVersions = object.peerOptionalDependencies[parts[0]];
56   // The resolved package
57   var moduleEntry = undefined;
58   // Module file
59   var moduleEntryFile = name;
60
61   try {
62     // Validate if it's possible to read the module
63     moduleEntry = require(moduleEntryFile);
64   } catch(err) {
65     // Attempt to resolve in top level package
66     try {
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);
72     } catch(err) {
73       if(err.code === 'MODULE_NOT_FOUND') return undefined;
74     }
75   }
76
77   // Resolve the location of the module's package.json file
78   var location = find_package_json(require.resolve(moduleEntryFile));
79   if(!location) {
80     throw new Error('package.json can not be located');
81   }
82
83   // Read the module file
84   var dependentOnModule = JSON.parse(fs.readFileSync(f('%s/package.json', location)));
85   // Get the version
86   var version = dependentOnModule.version;
87   // Validate if the found module satisfies the version id
88   if(semver.satisfies(version, expectedVersions) == false
89     && options.strict) {
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';
92       throw error;
93   }
94
95   // Satifies the module requirement
96   return moduleEntry;
97 }
98
99 require_optional.exists = function(name) {
100   try {
101     var m = require_optional(name);
102     if(m === undefined) return false;
103     return true;
104   } catch(err) {
105     return false;
106   }
107 }
108
109 module.exports = require_optional;