Skip to content

Do not detect proxy directories inside vendor directories as entrypoints #245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cold-wasps-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@arethetypeswrong/core": patch
---

Do not detect proxy directories inside vendor directories as entrypoints
45 changes: 33 additions & 12 deletions packages/core/src/internal/getEntrypointInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function getEntrypoints(fs: Package, exportsObject: unknown, options: CheckPacka
});
});
}

function formatEntrypointString(path: string, packageName: string) {
return (
path === "." || path.startsWith("./")
Expand All @@ -64,6 +65,7 @@ function formatEntrypointString(path: string, packageName: string) {
: `./${path}`
).trim();
}

function getSubpaths(exportsObject: any): string[] {
if (!exportsObject || typeof exportsObject !== "object" || Array.isArray(exportsObject)) {
return [];
Expand All @@ -74,22 +76,41 @@ function getSubpaths(exportsObject: any): string[] {
}
return keys.flatMap((key) => getSubpaths(exportsObject[key]));
}

function getProxyDirectories(rootDir: string, fs: Package) {
return fs
.listFiles()
.filter((f) => f.startsWith(rootDir) && f.endsWith("package.json"))
.filter((f) => {
const vendorDirectories = new Set<string>();
const proxyDirectories: string[] = [];
const files = fs.listFiles().sort((a, b) => a.length - b.length);
for (const file of files) {
if (file.startsWith(rootDir) && file.endsWith("/package.json")) {
try {
const packageJson = JSON.parse(fs.readFile(f));
return "main" in packageJson && (!packageJson.name || packageJson.name.startsWith(fs.packageName));
} catch {
return false;
const packageJson = JSON.parse(fs.readFile(file));
if (packageJson.name && !packageJson.name.startsWith(fs.packageName)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already here in the old code, but I didn't realize that the name mattered at all for these marker-style package.jsons; I figured it didn't really matter much

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole thing is just heuristics, but the idea is that your own subpackages are likely to be named "my-root-package/subdir" or not have a name at all. If the name is something else entirely, you’ve probably just vendored another package.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, I feel like ignoring nested node_modules would probablty also have worked (since that itself is a no-no that shouldn't have been able to happen)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would work for this case, but it wouldn't work for packages that vendor other packages in a folder not called node_modules, which next does. (It just happens not to have any vendored packages that contain subfolders with nameless package.json files.)

// Name unrelated to the root package, this is a vendored package
const vendorDir = file.slice(0, file.lastIndexOf("/"));
vendorDirectories.add(vendorDir);
} else if ("main" in packageJson && !isInsideVendorDirectory(file)) {
// No name or name starting with root package name, this is intended to be an entrypoint
const proxyDir = "." + file.slice(rootDir.length, file.lastIndexOf("/"));
proxyDirectories.push(proxyDir);
}
} catch {}
}
}

return proxyDirectories.sort((a, b) => {
return ts.comparePathsCaseInsensitive(a, b);
});

function isInsideVendorDirectory(file: string) {
return !!ts.forEachAncestorDirectory(file, (dir) => {
if (vendorDirectories.has(dir)) {
return true;
}
})
.map((f) => "." + f.slice(rootDir.length).slice(0, -`/package.json`.length))
.filter((f) => f !== "./")
.sort();
});
}
}

export function getEntrypointInfo(
packageName: string,
fs: Package,
Expand Down
Binary file not shown.
Loading