diff --git a/resolvers/deno/lib.rs b/resolvers/deno/lib.rs index 661caf836d..a74ca614a3 100644 --- a/resolvers/deno/lib.rs +++ b/resolvers/deno/lib.rs @@ -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() + } } - } }); } } diff --git a/resolvers/deno/npm/byonm.rs b/resolvers/deno/npm/byonm.rs index 771f23ce23..6e1be35ca0 100644 --- a/resolvers/deno/npm/byonm.rs +++ b/resolvers/deno/npm/byonm.rs @@ -205,9 +205,9 @@ impl ByonmNpmResolver { } // 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 ByonmNpmResolver { 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 ByonmNpmResolver { } } + // 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) } diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/__test__.jsonc b/tests/specs/npm/byonm_npm_specifier_in_node_modules/__test__.jsonc new file mode 100644 index 0000000000..e2c5495387 --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/__test__.jsonc @@ -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 + } + } +} diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/matches.ts b/tests/specs/npm/byonm_npm_specifier_in_node_modules/matches.ts new file mode 100644 index 0000000000..986e7baf4c --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/matches.ts @@ -0,0 +1,3 @@ +import { add } from "npm:package@1"; + +console.log(add(2, 3)); diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/aliased/index.js b/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/aliased/index.js new file mode 100644 index 0000000000..efe826ba65 --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/aliased/index.js @@ -0,0 +1,3 @@ +module.exports.add = function(a, b) { + return a + b; +}; diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/aliased/package.json b/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/aliased/package.json new file mode 100644 index 0000000000..618960872f --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/aliased/package.json @@ -0,0 +1,4 @@ +{ + "name": "not-same-name", + "version": "1.0.0" +} \ No newline at end of file diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/package/index.js b/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/package/index.js new file mode 100644 index 0000000000..efe826ba65 --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/package/index.js @@ -0,0 +1,3 @@ +module.exports.add = function(a, b) { + return a + b; +}; diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/package/package.json b/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/package/package.json new file mode 100644 index 0000000000..5723987e9f --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/node_modules/package/package.json @@ -0,0 +1,4 @@ +{ + "name": "package", + "version": "1.0.0" +} \ No newline at end of file diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches.out b/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches.out new file mode 100644 index 0000000000..c549e13ff2 --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches.out @@ -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] diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches.ts b/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches.ts new file mode 100644 index 0000000000..a337bd7d86 --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches.ts @@ -0,0 +1,3 @@ +import { add } from "npm:package@2"; // won't match 2 + +console.log(add(2, 3)); diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches_aliased.out b/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches_aliased.out new file mode 100644 index 0000000000..93b52f64bc --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches_aliased.out @@ -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] diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches_aliased.ts b/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches_aliased.ts new file mode 100644 index 0000000000..85fa11e319 --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/not_matches_aliased.ts @@ -0,0 +1,3 @@ +import { add } from "npm:aliased@1"; + +console.log(add(2, 3)); diff --git a/tests/specs/npm/byonm_npm_specifier_in_node_modules/package.json b/tests/specs/npm/byonm_npm_specifier_in_node_modules/package.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/npm/byonm_npm_specifier_in_node_modules/package.json @@ -0,0 +1,2 @@ +{ +}