From a420b0f7004699732d95601ae4eae99a1902a332 Mon Sep 17 00:00:00 2001 From: "alexander.akait" Date: Sun, 7 May 2023 20:18:48 +0300 Subject: [PATCH] fix: resolve for exports fields and exports fields --- lib/ExtensionAliasPlugin.js | 33 ++++- lib/forEachBail.js | 18 ++- test/exportsField.js | 121 ++++++++++++++++++ .../node_modules/@org/pkg/dist/string.js | 1 + .../@org/pkg/dist/string.test.d.ts | 1 + .../node_modules/@org/pkg/package.json | 9 ++ .../node_modules/pkg/dist/string.js | 1 + .../node_modules/pkg/dist/string.test.d.ts | 1 + .../node_modules/pkg/package.json | 9 ++ 9 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/dist/string.js create mode 100644 test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/dist/string.test.d.ts create mode 100644 test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/package.json create mode 100644 test/fixtures/exports-field-and-extension-alias/node_modules/pkg/dist/string.js create mode 100644 test/fixtures/exports-field-and-extension-alias/node_modules/pkg/dist/string.test.d.ts create mode 100644 test/fixtures/exports-field-and-extension-alias/node_modules/pkg/package.json diff --git a/lib/ExtensionAliasPlugin.js b/lib/ExtensionAliasPlugin.js index 76ce9b40..84e04635 100644 --- a/lib/ExtensionAliasPlugin.js +++ b/lib/ExtensionAliasPlugin.js @@ -36,17 +36,40 @@ module.exports = class ExtensionAliasPlugin { .tapAsync("ExtensionAliasPlugin", (request, resolveContext, callback) => { const requestPath = request.request; if (!requestPath || !requestPath.endsWith(extension)) return callback(); - const resolve = (alias, callback) => { - resolver.doResolve( + const isAliasString = typeof alias === "string"; + const resolve = (alias, callback, index) => { + const newRequest = `${requestPath.slice( + 0, + -extension.length + )}${alias}`; + + return resolver.doResolve( target, { ...request, - request: `${requestPath.slice(0, -extension.length)}${alias}`, + request: newRequest, fullySpecified: true }, `aliased from extension alias with mapping '${extension}' to '${alias}'`, resolveContext, - callback + (err, result) => { + // Throw error if we are on the last alias (for multiple aliases) and it failed, always throw if we are not an array or we have only one alias + if (!isAliasString && index) { + if (index !== this.options.alias.length) { + if (resolveContext.log) { + resolveContext.log( + `Failed to alias from extension alias with mapping '${extension}' to '${alias}' for '${newRequest}': ${err}` + ); + } + + return callback(null, result); + } + + return callback(err, result); + } else { + callback(err, result); + } + } ); }; @@ -56,7 +79,7 @@ module.exports = class ExtensionAliasPlugin { // Don't allow other aliasing or raw request return callback(null, null); }; - if (typeof alias === "string") { + if (isAliasString) { resolve(alias, stoppingCallback); } else if (alias.length > 1) { forEachBail(alias, resolve, stoppingCallback); diff --git a/lib/forEachBail.js b/lib/forEachBail.js index 031a562e..c3c989e3 100644 --- a/lib/forEachBail.js +++ b/lib/forEachBail.js @@ -11,13 +11,17 @@ module.exports = function forEachBail(array, iterator, callback) { let i = 0; const next = () => { let loop = undefined; - iterator(array[i++], (err, result) => { - if (err || result !== undefined || i >= array.length) { - return callback(err, result); - } - if (loop === false) while (next()); - loop = true; - }); + iterator( + array[i++], + (err, result) => { + if (err || result !== undefined || i >= array.length) { + return callback(err, result); + } + if (loop === false) while (next()); + loop = true; + }, + i + ); if (!loop) loop = false; return loop; }; diff --git a/test/exportsField.js b/test/exportsField.js index 035fc759..cf8089e0 100644 --- a/test/exportsField.js +++ b/test/exportsField.js @@ -2911,4 +2911,125 @@ describe("ExportsFieldPlugin", () => { } ); }); + + it("should resolve with the `extensionAlias` option", done => { + const resolver = ResolverFactory.createResolver({ + extensions: [".js"], + extensionAlias: { + ".js": [".ts", ".js"] + }, + fileSystem: nodeFileSystem, + fullySpecified: true, + conditionNames: ["webpack", "default"] + }); + const fixture = path.resolve( + __dirname, + "./fixtures/exports-field-and-extension-alias/" + ); + + resolver.resolve({}, fixture, "@org/pkg/string.js", {}, (err, result) => { + if (err) return done(err); + if (!result) throw new Error("No result"); + result.should.equal( + path.resolve(fixture, "./node_modules/@org/pkg/dist/string.js") + ); + done(); + }); + }); + + it("should resolve with the `extensionAlias` option #2", done => { + const resolver = ResolverFactory.createResolver({ + extensions: [".js"], + extensionAlias: { + ".js": [".ts", ".js"] + }, + fileSystem: nodeFileSystem, + fullySpecified: true, + conditionNames: ["webpack", "default"] + }); + const fixture = path.resolve( + __dirname, + "./fixtures/exports-field-and-extension-alias/" + ); + + resolver.resolve({}, fixture, "pkg/string.js", {}, (err, result) => { + if (err) return done(err); + if (!result) throw new Error("No result"); + result.should.equal( + path.resolve(fixture, "./node_modules/pkg/dist/string.js") + ); + done(); + }); + }); + + it("should resolve with the `extensionAlias` option #3", done => { + const resolver = ResolverFactory.createResolver({ + extensions: [".js"], + extensionAlias: { + ".js": [".foo", ".baz", ".baz", ".ts", ".js"] + }, + fileSystem: nodeFileSystem, + fullySpecified: true, + conditionNames: ["webpack", "default"] + }); + const fixture = path.resolve( + __dirname, + "./fixtures/exports-field-and-extension-alias/" + ); + + resolver.resolve({}, fixture, "pkg/string.js", {}, (err, result) => { + if (err) return done(err); + if (!result) throw new Error("No result"); + result.should.equal( + path.resolve(fixture, "./node_modules/pkg/dist/string.js") + ); + done(); + }); + }); + + it("should throw error with the `extensionAlias` option", done => { + const resolver = ResolverFactory.createResolver({ + extensions: [".js"], + extensionAlias: { + ".js": [".ts"] + }, + fileSystem: nodeFileSystem, + fullySpecified: true, + conditionNames: ["webpack", "default"] + }); + const fixture = path.resolve( + __dirname, + "./fixtures/exports-field-and-extension-alias/" + ); + + resolver.resolve({}, fixture, "pkg/string.js", {}, (err, result) => { + if (!err) throw new Error(`expect error, got ${result}`); + err.should.be.instanceof(Error); + err.message.should.match(/Package path \.\/string\.ts is not exported/); + done(); + }); + }); + + it("should throw error with the `extensionAlias` option #2", done => { + const resolver = ResolverFactory.createResolver({ + extensions: [".js"], + extensionAlias: { + ".js": ".ts" + }, + fileSystem: nodeFileSystem, + fullySpecified: true, + conditionNames: ["webpack", "default"] + }); + const fixture = path.resolve( + __dirname, + "./fixtures/exports-field-and-extension-alias/" + ); + + resolver.resolve({}, fixture, "pkg/string.js", {}, (err, result) => { + if (!err) throw new Error(`expect error, got ${result}`); + err.should.be.instanceof(Error); + err.message.should.match(/Package path \.\/string\.ts is not exported/); + done(); + }); + }); }); diff --git a/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/dist/string.js b/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/dist/string.js new file mode 100644 index 00000000..d1007aae --- /dev/null +++ b/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/dist/string.js @@ -0,0 +1 @@ +export default "string"; diff --git a/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/dist/string.test.d.ts b/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/dist/string.test.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/dist/string.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/package.json b/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/package.json new file mode 100644 index 00000000..b523a1e9 --- /dev/null +++ b/test/fixtures/exports-field-and-extension-alias/node_modules/@org/pkg/package.json @@ -0,0 +1,9 @@ +{ + "name": "@org/pkg", + "exports": { + "./*.js": { + "types": "./dist/*.d.ts", + "default": "./dist/*.js" + } + } +} diff --git a/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/dist/string.js b/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/dist/string.js new file mode 100644 index 00000000..d1007aae --- /dev/null +++ b/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/dist/string.js @@ -0,0 +1 @@ +export default "string"; diff --git a/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/dist/string.test.d.ts b/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/dist/string.test.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/dist/string.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/package.json b/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/package.json new file mode 100644 index 00000000..8e55fb46 --- /dev/null +++ b/test/fixtures/exports-field-and-extension-alias/node_modules/pkg/package.json @@ -0,0 +1,9 @@ +{ + "name": "@raviqqe/hidash", + "exports": { + "./*.js": { + "types": "./dist/*.d.ts", + "default": "./dist/*.js" + } + } +}