diff --git a/lib/node-modules-paths.js b/lib/node-modules-paths.js index 6e7fee2c..38276e71 100644 --- a/lib/node-modules-paths.js +++ b/lib/node-modules-paths.js @@ -2,24 +2,7 @@ var path = require('path'); var fs = require('fs'); var parse = path.parse || require('path-parse'); -module.exports = function nodeModulesPaths(start, opts, request) { - var modules = opts && opts.moduleDirectory - ? [].concat(opts.moduleDirectory) - : ['node_modules']; - - // ensure that `start` is an absolute path at this point, resolving against the process' current working directory - var absoluteStart = path.resolve(start); - - if (!opts || !opts.preserveSymlinks) { - try { - absoluteStart = fs.realpathSync(absoluteStart); - } catch (err) { - if (err.code !== 'ENOENT') { - throw err; - } - } - } - +var getNodeModulesDirs = function getNodeModulesDirs(absoluteStart, modules) { var prefix = '/'; if ((/^([A-Za-z]:)/).test(absoluteStart)) { prefix = ''; @@ -34,17 +17,40 @@ module.exports = function nodeModulesPaths(start, opts, request) { parsed = parse(parsed.dir); } - var dirs = paths.reduce(function (dirs, aPath) { + return paths.reduce(function (dirs, aPath) { return dirs.concat(modules.map(function (moduleDir) { return path.join(prefix, aPath, moduleDir); })); }, []); +}; - if (!opts || !opts.paths) { - return dirs; +module.exports = function nodeModulesPaths(start, opts, request) { + var modules = opts && opts.moduleDirectory + ? [].concat(opts.moduleDirectory) + : ['node_modules']; + + // ensure that `start` is an absolute path at this point, resolving against the process' current working directory + var absoluteStart = path.resolve(start); + + if (!opts || !opts.preserveSymlinks) { + try { + absoluteStart = fs.realpathSync(absoluteStart); + } catch (err) { + if (err.code !== 'ENOENT') { + throw err; + } + } } - if (typeof opts.paths === 'function') { - return dirs.concat(opts.paths(request, absoluteStart, opts)); + + if (opts && typeof opts.paths === 'function') { + return opts.paths( + request, + absoluteStart, + function () { return getNodeModulesDirs(absoluteStart, modules); }, + opts + ); } - return dirs.concat(opts.paths); + + var dirs = getNodeModulesDirs(absoluteStart, modules); + return opts && opts.paths ? dirs.concat(opts.paths) : dirs; }; diff --git a/readme.markdown b/readme.markdown index 9fb46bb7..db9d9400 100644 --- a/readme.markdown +++ b/readme.markdown @@ -77,6 +77,7 @@ options are: For advanced users, `paths` can also be a `opts.paths(request, start, opts)` function * request - the import specifier being resolved * start - lookup path + * getNodeModulesDirs - a thunk (no-argument function) that returns the paths using standard `node_modules` resolution * opts - the resolution options * opts.moduleDirectory - directory (or directories) in which to recursively look for modules. default: `"node_modules"` diff --git a/test/node-modules-paths.js b/test/node-modules-paths.js index 92efb9fa..1500fb19 100644 --- a/test/node-modules-paths.js +++ b/test/node-modules-paths.js @@ -65,8 +65,8 @@ test('node-modules-paths', function (t) { }); t.test('with paths=function option', function (t) { - var paths = function paths(request, absoluteStart, opts) { - return [path.join(absoluteStart, 'not node modules', request)]; + var paths = function paths(request, absoluteStart, getNodeModulesDirs, opts) { + return getNodeModulesDirs().concat(path.join(absoluteStart, 'not node modules', request)); }; var start = path.join(__dirname, 'resolver'); @@ -77,6 +77,16 @@ test('node-modules-paths', function (t) { t.end(); }); + t.test('with paths=function skipping node modules resolution', function (t) { + var paths = function paths(request, absoluteStart, getNodeModulesDirs, opts) { + return []; + }; + var start = path.join(__dirname, 'resolver'); + var dirs = nodeModulesPaths(start, { paths: paths }); + t.deepEqual(dirs, [], 'no node_modules was computed'); + t.end(); + }); + t.test('with moduleDirectory option', function (t) { var start = path.join(__dirname, 'resolver'); var moduleDirectory = 'not node modules';