1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 04:52:26 -05:00

fix(npm): search node_modules folder for package matching npm specifier (#27345)

This commit is contained in:
David Sherret 2024-12-12 18:58:14 -05:00 committed by GitHub
parent b7564636b5
commit f4f64cbe2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 112 additions and 14 deletions

View file

@ -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()
}
}
}
});
}
}

View file

@ -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) =
@ -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");
@ -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)
}

View file

@ -0,0 +1,18 @@
{
"tests": {
"matches": {
"args": "run -A matches.ts",
"output": "5\n"
},
"not_matches": {
"args": "run -A not_matches.ts",
"output": "not_matches.out",
"exitCode": 1
},
"not_matches_aliased": {
"args": "run -A not_matches_aliased.ts",
"output": "not_matches_aliased.out",
"exitCode": 1
}
}
}

View file

@ -0,0 +1,3 @@
import { add } from "npm:package@1";
console.log(add(2, 3));

View file

@ -0,0 +1,3 @@
module.exports.add = function(a, b) {
return a + b;
};

View file

@ -0,0 +1,4 @@
{
"name": "not-same-name",
"version": "1.0.0"
}

View file

@ -0,0 +1,3 @@
module.exports.add = function(a, b) {
return a + b;
};

View file

@ -0,0 +1,4 @@
{
"name": "package",
"version": "1.0.0"
}

View file

@ -0,0 +1,2 @@
error: Could not find a matching package for 'npm:package@2' in the node_modules directory. Ensure you have all your JSR and npm dependencies listed in your deno.json or package.json, then run `deno install`. Alternatively, turn on auto-install by specifying `"nodeModulesDir": "auto"` in your deno.json file.
at file:///[WILDLINE]

View file

@ -0,0 +1,3 @@
import { add } from "npm:package@2"; // won't match 2
console.log(add(2, 3));

View file

@ -0,0 +1,2 @@
error: Could not find a matching package for 'npm:aliased@1' in the node_modules directory. Ensure you have all your JSR and npm dependencies listed in your deno.json or package.json, then run `deno install`. Alternatively, turn on auto-install by specifying `"nodeModulesDir": "auto"` in your deno.json file.
at file:///[WILDLINE]

View file

@ -0,0 +1,3 @@
import { add } from "npm:aliased@1";
console.log(add(2, 3));

View file

@ -0,0 +1,2 @@
{
}