Skip to content

Commit

Permalink
handle exports field when using PnP
Browse files Browse the repository at this point in the history
fixes #270
  • Loading branch information
sokra committed Dec 21, 2020
1 parent bca7065 commit 0c9e745
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 29 deletions.
12 changes: 9 additions & 3 deletions lib/PnpPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,16 @@ module.exports = class PnpPlugin {
// The trailing slash indicates to PnP that this value is a folder rather than a file
const issuer = `${request.path}/`;

const packageMatch = /^(@[^/]+\/)?[^/]+/.exec(req);
if (!packageMatch) return callback();

const packageName = packageMatch[0];
const innerRequest = `.${req.slice(packageName.length)}`;

let resolution;
let apiResolution;
try {
resolution = this.pnpApi.resolveToUnqualified(req, issuer, {
resolution = this.pnpApi.resolveToUnqualified(packageName, issuer, {
considerBuiltins: false
});
if (resolveContext.fileDependencies) {
Expand All @@ -67,7 +73,7 @@ module.exports = class PnpPlugin {
return callback(error);
}

if (resolution === req) return callback();
if (resolution === packageName) return callback();

if (apiResolution && resolveContext.fileDependencies) {
resolveContext.fileDependencies.add(apiResolution);
Expand All @@ -76,7 +82,7 @@ module.exports = class PnpPlugin {
const obj = {
...request,
path: resolution,
request: undefined,
request: innerRequest,
ignoreSymlinks: true,
fullySpecified:
request.fullySpecified && !/^(@[^/]+\/)?[^/]+$/.test(req)
Expand Down
4 changes: 3 additions & 1 deletion lib/ResolverFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,9 @@ exports.createResolver = function (options) {
new ModulesInHierachicDirectoriesPlugin("raw-module", item, "module")
);
if (item.includes("node_modules") && pnpApi) {
plugins.push(new PnpPlugin("raw-module", pnpApi, "relative"));
plugins.push(
new PnpPlugin("raw-module", pnpApi, "undescribed-resolve-in-package")
);
}
} else {
plugins.push(new ModulesInRootPlugin("raw-module", item, "module"));
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/pnp/pkg3/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 1;
8 changes: 8 additions & 0 deletions test/fixtures/pnp/pkg3/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@exports-field/core",
"version": "1.0.0",
"exports": {
".": "./a.js",
"./x": "./a.js"
}
}
63 changes: 38 additions & 25 deletions test/pnp.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,22 @@ describe("pnp", () => {
});
});
it("should resolve by going through the pnp api", done => {
pnpApi.mocks.set(
"pkg/dir/index.js",
path.resolve(fixture, "pkg/dir/index.js")
);
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
resolver.resolve({}, __dirname, "pkg/dir/index.js", {}, (err, result) => {
if (err) return done(err);
result.should.equal(path.resolve(fixture, "pkg/dir/index.js"));
done();
});
});
it("should not resolve a not fully specified request when fullySpecified is set", done => {
pnpApi.mocks.set("pkg/dir/index", path.resolve(fixture, "pkg/dir/index"));
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
resolver.resolve({}, __dirname, "pkg/dir/index", {}, (err, result) => {
err.should.be.instanceof(Error);
done();
});
});
it("should track dependency to the pnp api", done => {
pnpApi.mocks.set(
"pkg/dir/index.js",
path.resolve(fixture, "pkg/dir/index.js")
);
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
pnpApi.mocks.set("pnpapi", path.resolve(fixture, ".pnp.js"));
const fileDependencies = new Set();
resolver.resolve(
Expand Down Expand Up @@ -131,7 +125,7 @@ describe("pnp", () => {
"should not resolve symlinks",
isAdmin
? done => {
pnpApi.mocks.set("pkg/symlink", path.resolve(fixture, "pkg/symlink"));
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
resolverFuzzy.resolve(
{},
__dirname,
Expand All @@ -149,10 +143,7 @@ describe("pnp", () => {
: undefined
);
it("should properly deal with other extensions", done => {
pnpApi.mocks.set(
"@user/pkg/typescript",
path.resolve(fixture, "pkg/typescript")
);
pnpApi.mocks.set("@user/pkg", path.resolve(fixture, "pkg"));
resolverFuzzy.resolve(
{},
__dirname,
Expand All @@ -166,10 +157,7 @@ describe("pnp", () => {
);
});
it("should properly deal package.json alias", done => {
pnpApi.mocks.set(
"pkg/package-alias",
path.resolve(fixture, "pkg/package-alias")
);
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
resolverFuzzy.resolve(
{},
__dirname,
Expand All @@ -185,7 +173,7 @@ describe("pnp", () => {
);
});
it("should prefer normal modules over pnp resolves", done => {
pnpApi.mocks.set("m1/a.js", path.resolve(fixture, "pkg/a.js"));
pnpApi.mocks.set("m1", path.resolve(fixture, "pkg"));
resolver.resolve(
{},
path.resolve(__dirname, "fixtures"),
Expand All @@ -199,10 +187,7 @@ describe("pnp", () => {
);
});
it("should prefer alias over pnp resolves", done => {
pnpApi.mocks.set(
"alias/index.js",
path.resolve(fixture, "pkg/dir/index.js")
);
pnpApi.mocks.set("alias", path.resolve(fixture, "pkg/dir"));
resolver.resolve(
{},
path.resolve(__dirname, "fixtures"),
Expand All @@ -216,11 +201,11 @@ describe("pnp", () => {
);
});
it("should prefer pnp over modules after node_modules", done => {
pnpApi.mocks.set("m2/a.js", path.resolve(fixture, "pkg/index.js"));
pnpApi.mocks.set("m2", path.resolve(fixture, "pkg"));
resolver.resolve(
{},
path.resolve(__dirname, "fixtures"),
"m2/a.js",
"m2/index.js",
{},
(err, result) => {
if (err) return done(err);
Expand All @@ -242,4 +227,32 @@ describe("pnp", () => {
}
);
});
it("should handle the exports field when using PnP", done => {
pnpApi.mocks.set("m1", path.resolve(fixture, "pkg3"));
resolver.resolve(
{},
path.resolve(__dirname, "fixtures"),
"m1",
{},
(err, result) => {
if (err) return done(err);
result.should.equal(path.resolve(fixture, "pkg3/a.js"));
done();
}
);
});
it("should handle the exports field when using PnP (with sub path)", done => {
pnpApi.mocks.set("@user/m1", path.resolve(fixture, "pkg3"));
resolver.resolve(
{},
path.resolve(__dirname, "fixtures"),
"@user/m1/x",
{},
(err, result) => {
if (err) return done(err);
result.should.equal(path.resolve(fixture, "pkg3/a.js"));
done();
}
);
});
});

0 comments on commit 0c9e745

Please sign in to comment.