Skip to content
This repository has been archived by the owner on Aug 13, 2022. It is now read-only.

Commit

Permalink
Add two-pass resolve is missing package.json:main (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-roemer authored Jun 2, 2021
1 parent f1b973f commit 012f8e9
Show file tree
Hide file tree
Showing 5 changed files with 553 additions and 226 deletions.
60 changes: 49 additions & 11 deletions lib/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,71 @@ const getLastPackageSegment = (filePath) => {
return relPath || null;
};

// TODO: ADD TESTS!!!
// Get path up to and including the package name (but no further).
const getLastPackageRoot = (filePath) => {
if (!filePath) { return null; }

// Iterate all normalized parts of the file path and extract packages.
const parts = path.normalize(filePath).split(path.sep);
const lastModsIdx = parts.lastIndexOf("node_modules");
// Not within node_modules.
if (lastModsIdx === -1) { return null; }

// Scoped.
if ((parts[lastModsIdx + 1] || "")[0] === "@" && parts[lastModsIdx + 2]) {
return parts.slice(0, lastModsIdx + 3).join(path.sep);
// Not within node_modules or potential path possibility.
if (lastModsIdx === -1 || lastModsIdx + 1 === parts.length) { return null; }

// Find package root index. Start with unscoped.
let pkgRootIdx = lastModsIdx + 1;
if (parts[pkgRootIdx][0] === "@") {
// Check possible scoped path possibility.
if (pkgRootIdx + 1 === parts.length) { return null; }
// Scoped.
pkgRootIdx++;
}

return parts.slice(0, pkgRootIdx + 1).join(path.sep);
};

// Return module name and relative path (as array of path parts).
const getDependencyParts = (dep) => {
if (
!dep
|| path.isAbsolute(dep)
|| dep.startsWith(".")
) {
return null;
}

// Note that `package.json:exports` don't normalize/resolve `..` or file
// paths, so leave them intact (which means manually replace `\\` instead
// of using `toPosixPath`).
let parts = dep
.replace(/\\/g, "/")
.split("/")
.filter(Boolean);

let name;
if (parts.length > 0) {
if (parts[0][0] === "@") {
if (parts[1]) {
name = `${parts[0]}/${parts[1]}`;
parts = parts.slice(2); // eslint-disable-line no-magic-numbers
}
} else if (parts[0]) {
name = parts[0];
parts = parts.slice(1);
}
}

// Unscoped
if (parts[lastModsIdx + 1]) {
return parts.slice(0, lastModsIdx + 2).join(path.sep);
if (!name) {
return null;
}

return null;
return { name, parts };
};

module.exports = {
getPackages,
getLastPackage,
getLastPackageSegment,
getLastPackageRoot
getLastPackageRoot,
getDependencyParts
};
9 changes: 9 additions & 0 deletions lib/path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";

const path = require("path");

const toPosixPath = (file) => !file ? file : path.normalize(file).replace(/\\/g, "/");

module.exports = {
toPosixPath
};
Loading

0 comments on commit 012f8e9

Please sign in to comment.