Skip to content
This repository has been archived by the owner on Jan 6, 2024. It is now read-only.

Commit

Permalink
Merge branch 'fix-missing-package-exports'
Browse files Browse the repository at this point in the history
  • Loading branch information
k-g-a committed Jul 5, 2021
2 parents 3546970 + 1f58816 commit 9c46d4e
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 22 deletions.
94 changes: 73 additions & 21 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,91 @@
const fs = require("fs");
const path = require("path");

function findMainPackageJson(entryPath, packageName) {
entryPath = entryPath.replace(/\//g, path.sep);
let directoryName = path.dirname(entryPath);
while (directoryName && !directoryName.endsWith(packageName)) {
const parentDirectoryName = path.resolve(directoryName, "..");
if (parentDirectoryName === directoryName) {
break;
}
directoryName = parentDirectoryName;
}

const suspect = path.resolve(directoryName, "package.json");
if (fs.existsSync(suspect)) {
return JSON.parse(fs.readFileSync(suspect).toString());
}

return null;
}

module.exports = (request, options) => {
let pkgName = "";
let packageName = "";
let submoduleName = "";

// NOTE: jest-sequencer is a special prefixed jest request
if (
const isNodeModuleRequest =
!request.startsWith(".") &&
!request.startsWith("/") &&
!request.startsWith("jest-sequencer")
) {
!request.startsWith("jest-sequencer");

if (isNodeModuleRequest) {
const pkgPathParts = request.split("/");
if (request.startsWith("@") && pkgPathParts.length > 2) {
pkgName = pkgPathParts.slice(0, 2).join("/");
packageName = pkgPathParts.slice(0, 2).join("/");
submoduleName = `./${pkgPathParts.slice(2).join("/")}`;
} else if (!request.startsWith("@") && pkgPathParts.length > 1) {
pkgName = pkgPathParts[0];
packageName = pkgPathParts[0];
submoduleName = `./${pkgPathParts.slice(1).join("/")}`;
}
}

const submoduleHasExtension = /\.\w+$/.test(submoduleName);
if (pkgName && submoduleName && !submoduleHasExtension) {
let pkg;
const extension = path.extname(submoduleName);
if (packageName && submoduleName && !extension) {
let packageJson = undefined;

try {
pkg = require(`${pkgName}/package.json`);
} catch (e) {
console.log(`Error while trying to get ${pkgName}'s package.json:`);
console.error(e);
packageJson = require(`${packageName}/package.json`);
} catch (requireError) {
if (requireError.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
// modules's package.json does not provide the "./package.json" path at it's "exports" field
// try to resolve manually
try {
const requestPath = require.resolve(packageName);
packageJson =
requestPath && findMainPackageJson(requestPath, packageName);
} catch (resolveError) {
if (resolveError.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
console.warn(
`Could not retrieve package.json neither through require (package.json itself is not within "exports" field), nor through require.resolve (package.json does not specify "main" field) - falling back to default resolver logic`
);
} else {
console.log(
`Unexpected error while performing require.resolve(${packageName}):`
);
console.error(resolveError);
return null;
}
}
} else {
console.log(`Unexpected error while requiring ${packageName}:`);
console.error(requireError);
return null;
}
}

if (
pkg &&
pkg.exports &&
Object.keys(pkg.exports).every((k) => k.startsWith("."))
) {
const exportValue = pkg.exports[submoduleName];
if (!packageJson) {
console.error(`Failed to find package.json for ${packageName}`);
}

const hasExports = packageJson && packageJson.exports;
const isEntryPointsExports =
hasExports &&
Object.keys(packageJson.exports).every((k) => k.startsWith("."));

if (hasExports && isEntryPointsExports) {
const exportValue = packageJson.exports[submoduleName];

let targetFilePath;
if (typeof exportValue === "string") {
Expand All @@ -45,13 +97,13 @@ module.exports = (request, options) => {
targetFilePath = exportValue.require;
}

if (!targetFilePath && pkg.type !== "module") {
if (!targetFilePath && packageJson.type !== "module") {
targetFilePath = exportValue.default;
}
}

if (targetFilePath) {
const target = targetFilePath.replace("./", `${pkgName}/`);
const target = targetFilePath.replace("./", `${packageName}/`);
return options.defaultResolver(target, options);
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jest-node-exports-resolver",
"version": "1.0.1",
"version": "1.0.2",
"description": "Jest resolver to handle node's 'exports' package entry points.",
"main": "index.js",
"repository": "https://github.com/k-g-a/jest-node-exports-resolver.git",
Expand Down

0 comments on commit 9c46d4e

Please sign in to comment.