Skip to content

Commit 7ae5ca4

Browse files
fix: find the pnpapi the issuer belongs to
2 parents 58464fc + bf7b68f commit 7ae5ca4

File tree

6 files changed

+99
-11
lines changed

6 files changed

+99
-11
lines changed

lib/PnpPlugin.js

+26-4
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,21 @@
1010
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
1111
/**
1212
* @typedef {Object} PnpApiImpl
13-
* @property {function(string, string, object): string} resolveToUnqualified
13+
* @property {function(string, string, object): string | null} resolveToUnqualified
1414
*/
1515

1616
module.exports = class PnpPlugin {
1717
/**
1818
* @param {string | ResolveStepHook} source source
1919
* @param {PnpApiImpl} pnpApi pnpApi
2020
* @param {string | ResolveStepHook} target target
21+
* @param {string | ResolveStepHook} alternateTarget alternateTarget
2122
*/
22-
constructor(source, pnpApi, target) {
23+
constructor(source, pnpApi, target, alternateTarget) {
2324
this.source = source;
2425
this.pnpApi = pnpApi;
2526
this.target = target;
27+
this.alternateTarget = alternateTarget;
2628
}
2729

2830
/**
@@ -32,6 +34,7 @@ module.exports = class PnpPlugin {
3234
apply(resolver) {
3335
/** @type {ResolveStepHook} */
3436
const target = resolver.ensureHook(this.target);
37+
const alternateTarget = resolver.ensureHook(this.alternateTarget);
3538
resolver
3639
.getHook(this.source)
3740
.tapAsync("PnpPlugin", (request, resolveContext, callback) => {
@@ -47,14 +50,33 @@ module.exports = class PnpPlugin {
4750
const packageName = packageMatch[0];
4851
const innerRequest = `.${req.slice(packageName.length)}`;
4952

50-
/** @type {string|undefined} */
53+
/** @type {string|undefined|null} */
5154
let resolution;
52-
/** @type {string|undefined} */
55+
/** @type {string|undefined|null} */
5356
let apiResolution;
5457
try {
5558
resolution = this.pnpApi.resolveToUnqualified(packageName, issuer, {
5659
considerBuiltins: false
5760
});
61+
62+
if (resolution === null) {
63+
// This is either not a PnP managed issuer or it's a Node builtin
64+
// Try to continue resolving with our alternatives
65+
resolver.doResolve(
66+
alternateTarget,
67+
request,
68+
"issuer is not managed by a pnpapi",
69+
resolveContext,
70+
(err, result) => {
71+
if (err) return callback(err);
72+
if (result) return callback(null, result);
73+
// Skip alternatives
74+
return callback(null, null);
75+
}
76+
);
77+
return;
78+
}
79+
5880
if (resolveContext.fileDependencies) {
5981
apiResolution = this.pnpApi.resolveToUnqualified("pnpapi", issuer, {
6082
considerBuiltins: false

lib/ResolverFactory.js

+36-3
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,27 @@ function processPnpApiOption(option) {
125125
option === undefined &&
126126
/** @type {NodeJS.ProcessVersions & {pnp: string}} */ versions.pnp
127127
) {
128-
// @ts-ignore
129-
return require("pnpapi"); // eslint-disable-line node/no-missing-require
128+
const _findPnpApi =
129+
/** @type {function(string): PnpApi | null}} */
130+
(
131+
// @ts-ignore
132+
require("module").findPnpApi
133+
);
134+
135+
if (_findPnpApi) {
136+
return {
137+
resolveToUnqualified(request, issuer, opts) {
138+
const pnpapi = _findPnpApi(issuer);
139+
140+
if (!pnpapi) {
141+
// Issuer isn't managed by PnP
142+
return null;
143+
}
144+
145+
return pnpapi.resolveToUnqualified(request, issuer, opts);
146+
}
147+
};
148+
}
130149
}
131150

132151
return option || null;
@@ -305,6 +324,7 @@ exports.createResolver = function (options) {
305324
resolver.ensureHook("normalResolve");
306325
resolver.ensureHook("internal");
307326
resolver.ensureHook("rawModule");
327+
resolver.ensureHook("alternateRawModule");
308328
resolver.ensureHook("module");
309329
resolver.ensureHook("resolveAsModule");
310330
resolver.ensureHook("undescribedResolveInPackage");
@@ -446,7 +466,20 @@ exports.createResolver = function (options) {
446466
)
447467
);
448468
plugins.push(
449-
new PnpPlugin("raw-module", pnpApi, "undescribed-resolve-in-package")
469+
new PnpPlugin(
470+
"raw-module",
471+
pnpApi,
472+
"undescribed-resolve-in-package",
473+
"alternate-raw-module"
474+
)
475+
);
476+
477+
plugins.push(
478+
new ModulesInHierarchicalDirectoriesPlugin(
479+
"alternate-raw-module",
480+
["node_modules"],
481+
"module"
482+
)
450483
);
451484
} else {
452485
plugins.push(

lib/util/module-browser.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Tobias Koppers @sokra
4+
*/
5+
6+
"use strict";
7+
8+
module.exports = {};

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
"LICENSE"
1010
],
1111
"browser": {
12-
"pnpapi": false,
13-
"process": "./lib/util/process-browser.js"
12+
"process": "./lib/util/process-browser.js",
13+
"module": "./lib/util/module-browser.js"
1414
},
1515
"dependencies": {
1616
"graceful-fs": "^4.2.4",

test/pnp.test.js

+22-1
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ describe("pnp", () => {
3535
beforeEach(() => {
3636
pnpApi = /** @type {any} */ ({
3737
mocks: new Map(),
38+
ignoredIssuers: new Set(),
3839
resolveToUnqualified(request, issuer) {
39-
if (pnpApi.mocks.has(request)) {
40+
if (pnpApi.ignoredIssuers.has(issuer)) {
41+
return null;
42+
} else if (pnpApi.mocks.has(request)) {
4043
return pnpApi.mocks.get(request);
4144
} else {
4245
const err = /** @type {any} */ (new Error(`No way`));
@@ -250,6 +253,24 @@ describe("pnp", () => {
250253
}
251254
);
252255
});
256+
it("should fallback to alternatives when pnp doesn't manage the issuer", done => {
257+
pnpApi.ignoredIssuers.add(path.resolve(__dirname, "fixtures") + "/");
258+
// Add the wrong path on purpose to make sure the issuer is ignored
259+
pnpApi.mocks.set("m2", path.resolve(fixture, "pkg"));
260+
resolver.resolve(
261+
{},
262+
path.resolve(__dirname, "fixtures"),
263+
"m2/b.js",
264+
{},
265+
(err, result) => {
266+
if (err) return done(err);
267+
expect(result).toEqual(
268+
path.resolve(__dirname, "fixtures/node_modules/m2/b.js")
269+
);
270+
done();
271+
}
272+
);
273+
});
253274
it("should handle the exports field when using PnP", done => {
254275
pnpApi.mocks.set("m1", path.resolve(fixture, "pkg3"));
255276
resolver.resolve(

types.d.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,11 @@ type Plugin =
289289
| { apply: (arg0: Resolver) => void }
290290
| ((this: Resolver, arg1: Resolver) => void);
291291
declare interface PnpApiImpl {
292-
resolveToUnqualified: (arg0: string, arg1: string, arg2: object) => string;
292+
resolveToUnqualified: (
293+
arg0: string,
294+
arg1: string,
295+
arg2: object
296+
) => null | string;
293297
}
294298
declare interface PossibleFileSystemError {
295299
code?: string;

0 commit comments

Comments
 (0)