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

Adds support for PnP #168

Closed
wants to merge 6 commits into from
Closed
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
40 changes: 40 additions & 0 deletions lib/PnpPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use strict";

module.exports = class PnpPlugin {
constructor(source, pnpApi, target) {
this.source = source;
this.pnpApi = pnpApi;
this.target = target;
}

apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver
.getHook(this.source)
.tapAsync("PnpPlugin", (requestContext, resolveContext, callback) => {
const request = requestContext.request;

// The trailing slash indicates to PnP that this value is a folder rather than a file
const issuer = `${requestContext.path}/`;

let resolution;
try {
resolution = this.pnpApi.resolveToUnqualified(request, issuer, {
considerBuiltins: false
});
} catch (error) {
return callback(error);
}

resolver.doResolve(
target,
Object.assign({}, requestContext, {
request: resolution
}),
null,
resolveContext,
callback
);
});
}
};
18 changes: 17 additions & 1 deletion lib/ResolverFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const AppendPlugin = require("./AppendPlugin");
const ResultPlugin = require("./ResultPlugin");
const ModuleAppendPlugin = require("./ModuleAppendPlugin");
const UnsafeCachePlugin = require("./UnsafeCachePlugin");
const PnpPlugin = require("./PnpPlugin");

exports.createResolver = function(options) {
//// OPTIONS ////
Expand Down Expand Up @@ -67,9 +68,23 @@ exports.createResolver = function(options) {
// A list of module alias configurations or an object which maps key to value
let alias = options.alias || [];

// A PnP API that should be used - null is "never", undefined is "auto"
const pnpApi =
typeof options.pnpApi === "undefined"
? process.versions.pnp
? require("pnpapi") // eslint-disable-line node/no-missing-require
: null
: options.pnpApi;

// Resolve symlinks to their symlinked location
const symlinks =
typeof options.symlinks !== "undefined" ? options.symlinks : true;
typeof options.symlinks !== "undefined"
? options.symlinks
: // PnP currently needs symlinks to be preserved to resolve peer dependencies
// Ref: https://github.com/webpack/enhanced-resolve/pull/168/files#r268819172
pnpApi
? false
: true;

// Resolve to a context instead of a file
const resolveToContext = options.resolveToContext || false;
Expand Down Expand Up @@ -215,6 +230,7 @@ exports.createResolver = function(options) {
plugins.push(new TryNextPlugin("raw-module", null, "module"));

// module
if (pnpApi) plugins.push(new PnpPlugin("before-module", pnpApi, "resolve"));
modules.forEach(item => {
if (Array.isArray(item))
plugins.push(
Expand Down
Empty file.
Empty file added test/fixtures/pnp/pkg/index.js
Empty file.
1 change: 1 addition & 0 deletions test/fixtures/pnp/pkg/symlink
Empty file.
67 changes: 67 additions & 0 deletions test/pnp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
var path = require("path");
require("should");
var ResolverFactory = require("../lib/ResolverFactory");
var NodeJsInputFileSystem = require("../lib/NodeJsInputFileSystem");
var CachedInputFileSystem = require("../lib/CachedInputFileSystem");

var pnpApi = {
mocks: new Map(),
resolveToUnqualified(request, issuer) {
if (pnpApi.mocks.has(request)) {
return pnpApi.mocks.get(request);
} else {
throw new Error(`No way`);
}
}
};

var nodeFileSystem = new CachedInputFileSystem(
new NodeJsInputFileSystem(),
4000
);

var resolver = ResolverFactory.createResolver({
extensions: [".ts", ".js"],
fileSystem: nodeFileSystem,
pnpApi
});

var fixture = path.resolve(__dirname, "fixtures", "pnp");

describe("extensions", function() {
it("should resolve by going through the pnp api", function(done) {
pnpApi.mocks.set(
"pkg/dir/index.js",
path.resolve(fixture, "pkg/dir/index.js")
);
resolver.resolve({}, fixture, "pkg/dir/index.js", {}, function(
err,
result
) {
console.log(err);
result.should.equal(path.resolve(fixture, "pkg/dir/index.js"));
done();
});
});
it("should resolve module names", function(done) {
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
resolver.resolve({}, fixture, "pkg", {}, function(err, result) {
result.should.equal(path.resolve(fixture, "pkg/index.js"));
done();
});
});
it("should not resolve symlinks", function(done) {
pnpApi.mocks.set("pkg/symlink", path.resolve(fixture, "pkg/symlink"));
resolver.resolve({}, fixture, "pkg/symlink", {}, function(err, result) {
result.should.equal(path.resolve(fixture, "pkg/symlink/index.js"));
done();
});
});
it("should properly deal with other extensions", function(done) {
pnpApi.mocks.set("pkg/typescript", path.resolve(fixture, "pkg/typescript"));
resolver.resolve({}, fixture, "pkg/typescript", {}, function(err, result) {
result.should.equal(path.resolve(fixture, "pkg/typescript/index.ts"));
done();
});
});
});