Skip to content

Commit

Permalink
fix: find the pnpapi the issuer belongs to
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Feb 27, 2024
2 parents 58464fc + bf7b68f commit 7ae5ca4
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 11 deletions.
30 changes: 26 additions & 4 deletions lib/PnpPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@
/** @typedef {import("./Resolver").ResolveRequest} ResolveRequest */
/**
* @typedef {Object} PnpApiImpl
* @property {function(string, string, object): string} resolveToUnqualified
* @property {function(string, string, object): string | null} resolveToUnqualified
*/

module.exports = class PnpPlugin {
/**
* @param {string | ResolveStepHook} source source
* @param {PnpApiImpl} pnpApi pnpApi
* @param {string | ResolveStepHook} target target
* @param {string | ResolveStepHook} alternateTarget alternateTarget
*/
constructor(source, pnpApi, target) {
constructor(source, pnpApi, target, alternateTarget) {
this.source = source;
this.pnpApi = pnpApi;
this.target = target;
this.alternateTarget = alternateTarget;
}

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

/** @type {string|undefined} */
/** @type {string|undefined|null} */
let resolution;
/** @type {string|undefined} */
/** @type {string|undefined|null} */
let apiResolution;
try {
resolution = this.pnpApi.resolveToUnqualified(packageName, issuer, {
considerBuiltins: false
});

if (resolution === null) {
// This is either not a PnP managed issuer or it's a Node builtin
// Try to continue resolving with our alternatives
resolver.doResolve(
alternateTarget,
request,
"issuer is not managed by a pnpapi",
resolveContext,
(err, result) => {
if (err) return callback(err);
if (result) return callback(null, result);
// Skip alternatives
return callback(null, null);
}
);
return;
}

if (resolveContext.fileDependencies) {
apiResolution = this.pnpApi.resolveToUnqualified("pnpapi", issuer, {
considerBuiltins: false
Expand Down
39 changes: 36 additions & 3 deletions lib/ResolverFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,27 @@ function processPnpApiOption(option) {
option === undefined &&
/** @type {NodeJS.ProcessVersions & {pnp: string}} */ versions.pnp
) {
// @ts-ignore
return require("pnpapi"); // eslint-disable-line node/no-missing-require
const _findPnpApi =
/** @type {function(string): PnpApi | null}} */
(
// @ts-ignore
require("module").findPnpApi
);

if (_findPnpApi) {
return {
resolveToUnqualified(request, issuer, opts) {
const pnpapi = _findPnpApi(issuer);

if (!pnpapi) {
// Issuer isn't managed by PnP
return null;
}

return pnpapi.resolveToUnqualified(request, issuer, opts);
}
};
}
}

return option || null;
Expand Down Expand Up @@ -305,6 +324,7 @@ exports.createResolver = function (options) {
resolver.ensureHook("normalResolve");
resolver.ensureHook("internal");
resolver.ensureHook("rawModule");
resolver.ensureHook("alternateRawModule");
resolver.ensureHook("module");
resolver.ensureHook("resolveAsModule");
resolver.ensureHook("undescribedResolveInPackage");
Expand Down Expand Up @@ -446,7 +466,20 @@ exports.createResolver = function (options) {
)
);
plugins.push(
new PnpPlugin("raw-module", pnpApi, "undescribed-resolve-in-package")
new PnpPlugin(
"raw-module",
pnpApi,
"undescribed-resolve-in-package",
"alternate-raw-module"
)
);

plugins.push(
new ModulesInHierarchicalDirectoriesPlugin(
"alternate-raw-module",
["node_modules"],
"module"
)
);
} else {
plugins.push(
Expand Down
8 changes: 8 additions & 0 deletions lib/util/module-browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/

"use strict";

module.exports = {};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"LICENSE"
],
"browser": {
"pnpapi": false,
"process": "./lib/util/process-browser.js"
"process": "./lib/util/process-browser.js",
"module": "./lib/util/module-browser.js"
},
"dependencies": {
"graceful-fs": "^4.2.4",
Expand Down
23 changes: 22 additions & 1 deletion test/pnp.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ describe("pnp", () => {
beforeEach(() => {
pnpApi = /** @type {any} */ ({
mocks: new Map(),
ignoredIssuers: new Set(),
resolveToUnqualified(request, issuer) {
if (pnpApi.mocks.has(request)) {
if (pnpApi.ignoredIssuers.has(issuer)) {
return null;
} else if (pnpApi.mocks.has(request)) {
return pnpApi.mocks.get(request);
} else {
const err = /** @type {any} */ (new Error(`No way`));
Expand Down Expand Up @@ -250,6 +253,24 @@ describe("pnp", () => {
}
);
});
it("should fallback to alternatives when pnp doesn't manage the issuer", done => {
pnpApi.ignoredIssuers.add(path.resolve(__dirname, "fixtures") + "/");
// Add the wrong path on purpose to make sure the issuer is ignored
pnpApi.mocks.set("m2", path.resolve(fixture, "pkg"));
resolver.resolve(
{},
path.resolve(__dirname, "fixtures"),
"m2/b.js",
{},
(err, result) => {
if (err) return done(err);
expect(result).toEqual(
path.resolve(__dirname, "fixtures/node_modules/m2/b.js")
);
done();
}
);
});
it("should handle the exports field when using PnP", done => {
pnpApi.mocks.set("m1", path.resolve(fixture, "pkg3"));
resolver.resolve(
Expand Down
6 changes: 5 additions & 1 deletion types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,11 @@ type Plugin =
| { apply: (arg0: Resolver) => void }
| ((this: Resolver, arg1: Resolver) => void);
declare interface PnpApiImpl {
resolveToUnqualified: (arg0: string, arg1: string, arg2: object) => string;
resolveToUnqualified: (
arg0: string,
arg1: string,
arg2: object
) => null | string;
}
declare interface PossibleFileSystemError {
code?: string;
Expand Down

0 comments on commit 7ae5ca4

Please sign in to comment.