Skip to content

Commit

Permalink
fix(npm): search node_modules folder for package matching npm specifi…
Browse files Browse the repository at this point in the history
…er (#27345)
  • Loading branch information
dsherret authored Dec 12, 2024
1 parent b756463 commit f4f64cb
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 14 deletions.
18 changes: 9 additions & 9 deletions resolvers/deno/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,16 +355,16 @@ impl<
})
.map_err(|err| {
match err.into_kind() {
ResolveReqWithSubPathErrorKind::MissingPackageNodeModulesFolder(
err,
) => err.into(),
ResolveReqWithSubPathErrorKind::ResolvePkgFolderFromDenoReq(
err,
) => err.into(),
ResolveReqWithSubPathErrorKind::PackageSubpathResolve(err) => {
err.into()
ResolveReqWithSubPathErrorKind::MissingPackageNodeModulesFolder(
err,
) => err.into(),
ResolveReqWithSubPathErrorKind::ResolvePkgFolderFromDenoReq(
err,
) => err.into(),
ResolveReqWithSubPathErrorKind::PackageSubpathResolve(err) => {
err.into()
}
}
}
});
}
}
Expand Down
61 changes: 56 additions & 5 deletions resolvers/deno/npm/byonm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@ impl<Fs: DenoResolverFs, TEnv: NodeResolverEnv> ByonmNpmResolver<Fs, TEnv> {
}

// attempt to resolve the npm specifier from the referrer's package.json,
if let Ok(file_path) = url_to_file_path(referrer) {
let mut current_path = file_path.as_path();
while let Some(dir_path) = current_path.parent() {
let maybe_referrer_path = url_to_file_path(referrer).ok();
if let Some(file_path) = maybe_referrer_path {
for dir_path in file_path.as_path().ancestors().skip(1) {
let package_json_path = dir_path.join("package.json");
if let Some(pkg_json) = self.load_pkg_json(&package_json_path)? {
if let Some(alias) =
Expand All @@ -216,11 +216,10 @@ impl<Fs: DenoResolverFs, TEnv: NodeResolverEnv> ByonmNpmResolver<Fs, TEnv> {
return Ok(Some((pkg_json, alias)));
}
}
current_path = dir_path;
}
}

// otherwise, fall fallback to the project's package.json
// fall fallback to the project's package.json
if let Some(root_node_modules_dir) = &self.root_node_modules_dir {
let root_pkg_json_path =
root_node_modules_dir.parent().unwrap().join("package.json");
Expand All @@ -232,6 +231,58 @@ impl<Fs: DenoResolverFs, TEnv: NodeResolverEnv> ByonmNpmResolver<Fs, TEnv> {
}
}

// now try to resolve based on the closest node_modules directory
let maybe_referrer_path = url_to_file_path(referrer).ok();
let search_node_modules = |node_modules: &Path| {
if req.version_req.tag().is_some() {
return None;
}

let pkg_folder = node_modules.join(&req.name);
if let Ok(Some(dep_pkg_json)) =
self.load_pkg_json(&pkg_folder.join("package.json"))
{
if dep_pkg_json.name.as_ref() == Some(&req.name) {
let matches_req = dep_pkg_json
.version
.as_ref()
.and_then(|v| Version::parse_from_npm(v).ok())
.map(|version| req.version_req.matches(&version))
.unwrap_or(true);
if matches_req {
return Some((dep_pkg_json, req.name.clone()));
}
}
}
None
};
if let Some(file_path) = &maybe_referrer_path {
for dir_path in file_path.as_path().ancestors().skip(1) {
if let Some(result) =
search_node_modules(&dir_path.join("node_modules"))
{
return Ok(Some(result));
}
}
}

// and finally check the root node_modules directory
if let Some(root_node_modules_dir) = &self.root_node_modules_dir {
let already_searched = maybe_referrer_path
.as_ref()
.and_then(|referrer_path| {
root_node_modules_dir
.parent()
.map(|root_dir| referrer_path.starts_with(root_dir))
})
.unwrap_or(false);
if !already_searched {
if let Some(result) = search_node_modules(root_node_modules_dir) {
return Ok(Some(result));
}
}
}

Ok(None)
}

Expand Down
18 changes: 18 additions & 0 deletions tests/specs/npm/byonm_npm_specifier_in_node_modules/__test__.jsonc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f4f64cb

Please sign in to comment.