var fs = require('fs') var path = require('path') var resolve = require('resolve').sync var rc = require('rc') var spawnSync = require('child_process').spawnSync var isWin32 = process.platform === 'win32' 'use strict'; // resolvers module.exports = [ nativeResolve, nodePathResolve, userHomeResolve, nodeModulesResolve, yarnModulesResolve, prefixResolve, execPathResolve ] function resolveFn(module, basePath, dirname) { try { return resolve(module, { basedir: path.join(basePath, dirname || '') }) } catch (e) {} } // resolve using native require() function // if NODE_PATH is defined, a global module should be natively resolved function nativeResolve(module, dirname) { try { return require.resolve(module, dirname) } catch (e) {} } // See: http://nodejs.org/docs/latest/api/modules.html#modules_loading_from_the_global_folders // required? function nodePathResolve(module, dirname) { var i, l, modulePath var nodePath = process.env.NODE_PATH if (!nodePath) { return } nodePath = nodePath.split(path.delimiter).map(function (nodepath) { return path.normalize(nodepath) }) for (i = 0, l = nodePath.length; i < l; i += 1) { if (modulePath = resolveFn(module, dirname || nodePath[i])) { break } } return modulePath } function userHomeResolve(module) { var i, l, modulePath var homePath = isWin32 ? process.env['USERPROFILE'] : process.env['HOME'] var paths = [ 'node_modules', 'node_libraries', 'node_packages' ] for (i = 0, l = paths.length; i < l; i += 1) { if (modulePath = resolveFn(module, homePath, paths[i])) { break; } } return modulePath } // See: https://npmjs.org/doc/files/npm-folders.html#prefix-Configuration // it uses execPath to discover the default prefix on *nix and %APPDATA% on Windows function prefixResolve(module) { var modulePath, dirname var prefix = rc('npm').prefix if (isWin32) { prefix = prefix || path.join(process.env.APPDATA, 'npm') dirname = prefix } else { prefix = prefix || path.join(path.dirname(process.execPath), '..') dirname = path.join(prefix, 'lib') } dirname = path.join(dirname, 'node_modules') modulePath = resolveFn(module, dirname) return modulePath } // Resolves packages using the node installation path // Useful for resolving global packages such as npm when the prefix has been overriden by the user function execPathResolve(module) { var modulePath, dirname var execPath = path.dirname(process.execPath) if (isWin32) { dirname = execPath } else { dirname = path.join(execPath, '..', 'lib') } dirname = path.join(dirname, 'node_modules') modulePath = resolveFn(module, dirname) return modulePath } function nodeModulesResolve(module) { var i, l, modulePath var nodeModules = process.env['NODE_MODULES'] if (typeof nodeModules === 'string') { nodeModules = nodeModules.split(path.delimiter) for (i = 0, l = nodeModules.length; i < l; i += 1) { if (modulePath = resolveFn(module, nodeModules[i])) { break; } } } return modulePath } function yarnModulesResolve(module) { var i, modulePath; // Retrieve yarn global path var yarnCmd = isWin32 ? 'yarn.cmd' : 'yarn'; var result = spawnSync(yarnCmd, ['global', 'dir'], { encoding: 'utf8' }); if (!result.error && result.stdout) { var yarnPath = result.stdout.replace(/[\r\n]+/g, ''); var nodeModulesStr = path.join(yarnPath, 'node_modules'); if (typeof nodeModulesStr === 'string') { var nodeModules = nodeModulesStr.split(path.delimiter); for (i = 0; i < nodeModules.length; i++) { if (modulePath = resolveFn(module, nodeModules[i])) { break; } } } } return modulePath; }