Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for package.json exports #320

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,12 @@ module.exports = function resolve(x, options, callback) {
return;
}

if (pkg && pkg.exports) {
var res = resolveExports(pkg.exports, ['require', 'node'], '.');
var exportPath = path.resolve(x, res);
return loadAsFile(exportPath, pkg, cb);
}

loadAsFile(path.join(x, '/index'), pkg, cb);
});
});
Expand Down
40 changes: 40 additions & 0 deletions lib/resolve-exports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Just walks the exports object synchronously looking for a match.
// Does not validate that the module it finds actually exists.

// Returns undefined if no match was found, null if a match was explicitly
// forbidden by setting the value to null in the exports object. Either
// null or undefined at the caller value have the same effective meaning,
// no match is available.
var resolveExports = function resolveExports (exp, conditions, sub) {
if (!exp) return exp;
if (typeof exp === 'string' && (sub === '.' || sub === null)) return exp;
// TODO: check if this should throw?
if (typeof exp !== 'object') return null;
if (Array.isArray(exp) && (sub === '.' || sub === null)) {
for (var i = 0; i < exp.length; i++) {
var resolved = resolveExports(exp[i], conditions);
if (resolved || resolved === null) return resolved;
}
}
if (sub !== null) {
if (Object.prototype.hasOwnProperty.call(exp, sub)) {
return resolveExports(exp[sub], conditions, null);
} else if (sub !== '.') {
// sub=./x, exports={require:'./y'}, not a match
return undefined;
}
}
var keys = Object.keys(exp);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (key === 'default') return resolveExports(exp[key], conditions, null);
var k = conditions.indexOf(key);
if (k !== -1) {
const resolved = resolveExports(exp[key], conditions, null);
if (resolved || resolved === null) return resolved;
}
}
return undefined;
}

module.exports = resolveExports;
7 changes: 7 additions & 0 deletions lib/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var getHomedir = require('./homedir');
var caller = require('./caller');
var nodeModulesPaths = require('./node-modules-paths');
var normalizeOptions = require('./normalize-options');
var resolveExports = require('./resolve-exports');

var realpathFS = process.platform !== 'win32' && fs.realpathSync && typeof fs.realpathSync.native === 'function' ? fs.realpathSync.native : fs.realpathSync;

Expand Down Expand Up @@ -199,6 +200,12 @@ module.exports = function resolveSync(x, options) {
incorrectMainError.code = 'INCORRECT_PACKAGE_MAIN';
throw incorrectMainError;
}

if (pkg && pkg.exports) {
var res = resolveExports(pkg.exports, ['require', 'node'], '.');
var exportPath = path.resolve(x, res);
return loadAsFileSync(exportPath);
}
}

return loadAsFileSync(path.join(x, '/index'));
Expand Down
Loading