Skip to content

Commit c6b3399

Browse files
sokraarcanis
andcommitted
add support for Yarn PnP
fixes #168 Co-authored-by: Maël Nison <nison.mael@gmail.com>
1 parent b0e5282 commit c6b3399

File tree

11 files changed

+216
-1
lines changed

11 files changed

+216
-1
lines changed

lib/PnpPlugin.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Maël Nison @arcanis
4+
*/
5+
6+
"use strict";
7+
8+
module.exports = class PnpPlugin {
9+
constructor(source, pnpApi, target) {
10+
this.source = source;
11+
this.pnpApi = pnpApi;
12+
this.target = target;
13+
}
14+
15+
apply(resolver) {
16+
const target = resolver.ensureHook(this.target);
17+
resolver
18+
.getHook(this.source)
19+
.tapAsync("PnpPlugin", (request, resolveContext, callback) => {
20+
const req = request.request;
21+
22+
// The trailing slash indicates to PnP that this value is a folder rather than a file
23+
const issuer = `${request.path}/`;
24+
25+
let resolution;
26+
try {
27+
resolution = this.pnpApi.resolveToUnqualified(req, issuer, {
28+
considerBuiltins: false
29+
});
30+
} catch (error) {
31+
return callback(error);
32+
}
33+
34+
if (resolution === req) return callback();
35+
36+
const obj = {
37+
...request,
38+
path: resolution,
39+
request: undefined,
40+
ignoreSymlinks: true
41+
};
42+
resolver.doResolve(
43+
target,
44+
obj,
45+
`resolved by pnp to ${resolution}`,
46+
resolveContext,
47+
(err, result) => {
48+
if (err) return callback(err);
49+
if (result) return callback(null, result);
50+
// Skip alternatives
51+
return callback(null, null);
52+
}
53+
);
54+
});
55+
}
56+
};

lib/ResolverFactory.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const UseFilePlugin = require("./UseFilePlugin");
2828
const AppendPlugin = require("./AppendPlugin");
2929
const ResultPlugin = require("./ResultPlugin");
3030
const UnsafeCachePlugin = require("./UnsafeCachePlugin");
31+
const PnpPlugin = require("./PnpPlugin");
3132

3233
exports.createResolver = function(options) {
3334
//// OPTIONS ////
@@ -61,6 +62,15 @@ exports.createResolver = function(options) {
6162
// A list of module alias configurations or an object which maps key to value
6263
let alias = options.alias || [];
6364

65+
// A PnP API that should be used - null is "never", undefined is "auto"
66+
const pnpApi =
67+
options.pnpApi === undefined
68+
? process.versions.pnp
69+
? // eslint-disable-next-line node/no-missing-require
70+
require("pnpapi")
71+
: null
72+
: options.pnpApi;
73+
6474
// Resolve symlinks to their symlinked location
6575
const symlinks =
6676
typeof options.symlinks !== "undefined" ? options.symlinks : true;
@@ -203,6 +213,9 @@ exports.createResolver = function(options) {
203213
plugins.push(new JoinRequestPlugin("after-described-resolve", "relative"));
204214

205215
// module
216+
if (pnpApi) {
217+
plugins.push(new PnpPlugin("raw-module", pnpApi, "relative"));
218+
}
206219
modules.forEach(item => {
207220
if (Array.isArray(item))
208221
plugins.push(
@@ -328,7 +341,8 @@ exports.createResolver = function(options) {
328341
plugins.push(new FileExistsPlugin("file", "existing-file"));
329342

330343
// existing-file
331-
if (symlinks) plugins.push(new SymlinkPlugin("existing-file", "relative"));
344+
if (symlinks)
345+
plugins.push(new SymlinkPlugin("existing-file", "existing-file"));
332346
plugins.push(new NextPlugin("existing-file", "resolved"));
333347
}
334348

lib/SymlinkPlugin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module.exports = class SymlinkPlugin {
2020
resolver
2121
.getHook(this.source)
2222
.tapAsync("SymlinkPlugin", (request, resolveContext, callback) => {
23+
if (request.ignoreSymlinks) return callback();
2324
const pathsResult = getPaths(request.path);
2425
const pathSeqments = pathsResult.seqments;
2526
const paths = pathsResult.paths;

test/fixtures/pnp/pkg/dir/index.js

Whitespace-only changes.

test/fixtures/pnp/pkg/index.js

Whitespace-only changes.

test/fixtures/pnp/pkg/main.js

Whitespace-only changes.

test/fixtures/pnp/pkg/package-alias/browser.js

Whitespace-only changes.

test/fixtures/pnp/pkg/package-alias/index.js

Whitespace-only changes.

test/fixtures/pnp/pkg/package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"main": "main.js",
3+
"browser": {
4+
"./package-alias/index.js": "./package-alias/browser.js",
5+
"module": "pkg/dir/index"
6+
}
7+
}

test/fixtures/pnp/pkg/typescript/index.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)