Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Supply package from which module was resolved to callback. #21

Closed
wants to merge 2 commits into from

2 participants

@jaredhanson

This patch will adds an opts.package options, which the caller sets to the package metadata of the package which the module is being resolved from. The callback takes a third (optional) argument which is the package metadata of the package from which the resolved module was found in.

For modules in the same package, this will be identical to the opts.package option passed in. If the module was loaded from a different package, it will be different, obviously.

This is part of a larger set of forthcoming patches that is ultimately designed to address the following issues:

substack/module-deps#7
substack/module-deps#13

Also, I only implemented this for the async resolve. It didn't seem useful to return an array from the sync resolve just to pass an optional package, and browser-resolve and module-deps don't use the sync version anyway.

I will update this PR with the other relevant PRs as I submit them. Cheers!

@substack
Owner

Published as 0.4.0. Thanks!

@substack substack closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
50 lib/async.js
@@ -28,40 +28,50 @@ module.exports = function resolve (x, opts, cb) {
opts.paths = opts.paths || [];
if (x.match(/^(?:\.\.?\/|\/|([A-Za-z]:)?\\)/)) {
- loadAsFile(path.resolve(y, x), function (err, m) {
+ loadAsFile(path.resolve(y, x), function (err, m, pkg) {
if (err) cb(err)
- else if (m) cb(null, m)
- else loadAsDirectory(path.resolve(y, x), function (err, d) {
+ else if (m) cb(null, m, pkg)
+ else loadAsDirectory(path.resolve(y, x), function (err, d, pkg) {
if (err) cb(err)
- else if (d) cb(null, d)
+ else if (d) cb(null, d, pkg)
else cb(new Error("Cannot find module '" + x + "'"))
})
});
}
- else loadNodeModules(x, y, function (err, n) {
+ else loadNodeModules(x, y, function (err, n, pkg) {
if (err) cb(err)
- else if (n) cb(null, n)
+ else if (n) cb(null, n, pkg)
else cb(new Error("Cannot find module '" + x + "'"))
});
- function loadAsFile (x, cb) {
+ function loadAsFile (x, pkg, cb) {
+ if (typeof pkg === 'function') {
+ cb = pkg;
+ pkg = opts.package;
+ }
+
(function load (exts) {
if (exts.length === 0) return cb(null, undefined);
var file = x + exts[0];
isFile(file, function (err, ex) {
if (err) cb(err)
- else if (ex) cb(null, file)
+ else if (ex) cb(null, file, pkg)
else load(exts.slice(1))
});
})([''].concat(extensions));
}
- function loadAsDirectory (x, cb) {
+ function loadAsDirectory (x, fpkg, cb) {
+ if (typeof fpkg === 'function') {
+ cb = fpkg;
+ fpkg = opts.package;
+ }
+
var pkgfile = path.join(x, '/package.json');
isFile(pkgfile, function (err, ex) {
if (err) return cb(err);
- if (!ex) return loadAsFile(path.join(x, '/index'), cb);
+ if (!ex) return loadAsFile(path.join(x, '/index'), fpkg, cb);
readFile(pkgfile, function (err, body) {
if (err) return cb(err);
@@ -75,20 +85,20 @@ module.exports = function resolve (x, opts, cb) {
}
if (pkg.main) {
- loadAsFile(path.resolve(x, pkg.main), function (err, m) {
+ loadAsFile(path.resolve(x, pkg.main), pkg, function (err, m, pkg) {
if (err) return cb(err);
- if (m) return cb(null, m);
+ if (m) return cb(null, m, pkg);
var dir = path.resolve(x, pkg.main);
- loadAsDirectory(dir, function (err, n) {
+ loadAsDirectory(dir, pkg, function (err, n, pkg) {
if (err) return cb(err);
- if (n) return cb(null, n);
- loadAsFile(path.join(x, '/index'), cb);
+ if (n) return cb(null, n, pkg);
+ loadAsFile(path.join(x, '/index'), pkg, cb);
});
});
return;
}
- loadAsFile(path.join(x, '/index'), cb);
+ loadAsFile(path.join(x, '/index'), pkg, cb);
});
});
}
@@ -98,12 +108,12 @@ module.exports = function resolve (x, opts, cb) {
if (dirs.length === 0) return cb(null, undefined);
var dir = dirs[0];
- loadAsFile(path.join(dir, '/', x), function (err, m) {
+ loadAsFile(path.join(dir, '/', x), undefined, function (err, m, pkg) {
if (err) return cb(err);
- if (m) return cb(null, m);
- loadAsDirectory(path.join(dir, '/', x), function (err, n) {
+ if (m) return cb(null, m, pkg);
+ loadAsDirectory(path.join(dir, '/', x), undefined, function (err, n, pkg) {
if (err) return cb(err);
- if (n) return cb(null, n);
+ if (n) return cb(null, n, pkg);
process(dirs.slice(1));
});
});
View
2  readme.markdown
@@ -51,6 +51,8 @@ options are:
* opts.basedir - directory to begin resolving from
+* opts.package - package from which module is being loaded
+
* opts.extensions - array of file extensions to search in order
* opts.readFile - how to read files asynchronously
View
5 test/filter.js
@@ -2,7 +2,7 @@ var test = require('tap').test;
var resolve = require('../');
test('filter', function (t) {
- t.plan(1);
+ t.plan(2);
var dir = __dirname + '/resolver';
resolve('./baz', {
basedir : dir,
@@ -10,8 +10,9 @@ test('filter', function (t) {
pkg.main = 'doom';
return pkg;
}
- }, function (err, res) {
+ }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/baz/doom.js');
+ t.equal(pkg.main, 'doom');
});
});
View
84 test/mock.js
@@ -2,7 +2,7 @@ var test = require('tap').test;
var resolve = require('../');
test('mock', function (t) {
- t.plan(4);
+ t.plan(6);
var files = {
'/foo/bar/baz.js' : 'beep'
@@ -20,14 +20,57 @@ test('mock', function (t) {
}
}
- resolve('./baz', opts('/foo/bar'), function (err, res) {
+ resolve('./baz', opts('/foo/bar'), function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, '/foo/bar/baz.js');
+ t.equal(pkg, undefined);
});
- resolve('./baz.js', opts('/foo/bar'), function (err, res) {
+ resolve('./baz.js', opts('/foo/bar'), function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, '/foo/bar/baz.js');
+ t.equal(pkg, undefined);
+ });
+
+ resolve('baz', opts('/foo/bar'), function (err, res) {
+ t.equal(err.message, "Cannot find module 'baz'");
+ });
+
+ resolve('../baz', opts('/foo/bar'), function (err, res) {
+ t.equal(err.message, "Cannot find module '../baz'");
+ });
+});
+
+test('mock from package', function (t) {
+ t.plan(6);
+
+ var files = {
+ '/foo/bar/baz.js' : 'beep'
+ };
+
+ function opts (basedir) {
+ return {
+ basedir : basedir,
+ package : { main: 'bar' },
+ isFile : function (file, cb) {
+ cb(null, files.hasOwnProperty(file));
+ },
+ readFile : function (file, cb) {
+ cb(null, files[file]);
+ }
+ }
+ }
+
+ resolve('./baz', opts('/foo/bar'), function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, '/foo/bar/baz.js');
+ t.equal(pkg.main, 'bar');
+ });
+
+ resolve('./baz.js', opts('/foo/bar'), function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, '/foo/bar/baz.js');
+ t.equal(pkg.main, 'bar');
});
resolve('baz', opts('/foo/bar'), function (err, res) {
@@ -40,7 +83,36 @@ test('mock', function (t) {
});
test('mock package', function (t) {
- t.plan(1);
+ t.plan(2);
+
+ var files = {
+ '/foo/node_modules/bar/baz.js' : 'beep',
+ '/foo/node_modules/bar/package.json' : JSON.stringify({
+ main : './baz.js'
+ })
+ };
+
+ function opts (basedir) {
+ return {
+ basedir : basedir,
+ isFile : function (file, cb) {
+ cb(null, files.hasOwnProperty(file));
+ },
+ readFile : function (file, cb) {
+ cb(null, files[file]);
+ }
+ }
+ }
+
+ resolve('bar', opts('/foo'), function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, '/foo/node_modules/bar/baz.js');
+ t.equal(pkg.main, './baz.js');
+ });
+});
+
+test('mock package from package', function (t) {
+ t.plan(2);
var files = {
'/foo/node_modules/bar/baz.js' : 'beep',
@@ -52,6 +124,7 @@ test('mock package', function (t) {
function opts (basedir) {
return {
basedir : basedir,
+ package : { main: 'bar' },
isFile : function (file, cb) {
cb(null, files.hasOwnProperty(file));
},
@@ -61,8 +134,9 @@ test('mock package', function (t) {
}
}
- resolve('bar', opts('/foo'), function (err, res) {
+ resolve('bar', opts('/foo'), function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, '/foo/node_modules/bar/baz.js');
+ t.equal(pkg.main, './baz.js');
});
});
View
90 test/resolver.js
@@ -2,17 +2,31 @@ var test = require('tap').test;
var resolve = require('../');
test('async foo', function (t) {
- t.plan(3);
+ t.plan(9);
var dir = __dirname + '/resolver';
- resolve('./foo', { basedir : dir }, function (err, res) {
+ resolve('./foo', { basedir : dir }, function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, dir + '/foo.js');
+ t.equal(pkg, undefined);
+ });
+
+ resolve('./foo.js', { basedir : dir }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/foo.js');
+ t.equal(pkg, undefined);
});
- resolve('./foo.js', { basedir : dir }, function (err, res) {
+ resolve('./foo', { basedir : dir, package: { main: 'resolver' } }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/foo.js');
+ t.equal(pkg.main, 'resolver');
+ });
+
+ resolve('./foo.js', { basedir : dir, package: { main: 'resolver' } }, function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, dir + '/foo.js');
+ t.equal(pkg.main, 'resolver');
});
resolve('foo', { basedir : dir }, function (err) {
@@ -21,57 +35,105 @@ test('async foo', function (t) {
});
test('bar', function (t) {
- t.plan(2);
+ t.plan(6);
var dir = __dirname + '/resolver';
- resolve('foo', { basedir : dir + '/bar' }, function (err, res) {
+ resolve('foo', { basedir : dir + '/bar' }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/bar/node_modules/foo/index.js');
+ t.equal(pkg, undefined);
});
- resolve('foo', { basedir : dir + '/bar' }, function (err, res) {
+ resolve('foo', { basedir : dir + '/bar' }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/bar/node_modules/foo/index.js');
+ t.equal(pkg, undefined);
+ });
+
+ resolve('foo', { basedir : dir + '/bar', package: { main: 'bar' } }, function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, dir + '/bar/node_modules/foo/index.js');
+ t.equal(pkg, undefined);
});
});
test('baz', function (t) {
- t.plan(1);
+ t.plan(4);
var dir = __dirname + '/resolver';
- resolve('./baz', { basedir : dir }, function (err, res) {
+ resolve('./baz', { basedir : dir }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/baz/quux.js');
+ t.equal(pkg.main, 'quux.js');
+ });
+
+ resolve('./baz', { basedir : dir, package: { main: 'resolver' } }, function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, dir + '/baz/quux.js');
+ t.equal(pkg.main, 'quux.js');
});
});
test('biz', function (t) {
- t.plan(3);
+ t.plan(12);
var dir = __dirname + '/resolver/biz/node_modules';
- resolve('./grux', { basedir : dir }, function (err, res) {
+ resolve('./grux', { basedir : dir }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/grux/index.js');
+ t.equal(pkg, undefined);
});
- resolve('tiv', { basedir : dir + '/grux' }, function (err, res) {
+ resolve('./grux', { basedir : dir, package: { main: 'biz' } }, function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, dir + '/grux/index.js');
+ t.equal(pkg.main, 'biz');
+ });
+
+ resolve('tiv', { basedir : dir + '/grux' }, function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, dir + '/tiv/index.js');
+ t.equal(pkg, undefined);
+ });
+
+ resolve('tiv', { basedir : dir + '/grux', package: { main: 'grux' } }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/tiv/index.js');
+ t.equal(pkg, undefined);
});
- resolve('grux', { basedir : dir + '/tiv' }, function (err, res) {
+ resolve('grux', { basedir : dir + '/tiv' }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/grux/index.js');
+ t.equal(pkg, undefined);
+ });
+
+ resolve('grux', { basedir : dir + '/tiv', package: { main: 'tiv' } }, function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, dir + '/grux/index.js');
+ t.equal(pkg, undefined);
+ });
+});
+
+test('quux', function (t) {
+ t.plan(2);
+ var dir = __dirname + '/resolver/quux';
+
+ resolve('./foo', { basedir : dir, package: { main: 'quux' } }, function (err, res, pkg) {
+ if (err) t.fail(err);
+ t.equal(res, dir + '/foo/index.js');
+ t.equal(pkg.main, 'quux');
});
});
test('normalize', function (t) {
- t.plan(1);
+ t.plan(2);
var dir = __dirname + '/resolver/biz/node_modules/grux';
- resolve('../grux', { basedir : dir }, function (err, res) {
+ resolve('../grux', { basedir : dir }, function (err, res, pkg) {
if (err) t.fail(err);
t.equal(res, dir + '/index.js');
+ t.equal(pkg, undefined);
});
});
View
1  test/resolver/quux/foo/index.js
@@ -0,0 +1 @@
+module.exports = 1;
Something went wrong with that request. Please try again.