diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2024-06-26 17:24:10 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-26 21:24:10 +0000 |
commit | 0da01c0ca6b537f74be32126e567bdfc2c73ed16 (patch) | |
tree | ef29d32cffb03a975a58c16827b0691dda50a5b3 /cli/npm/byonm.rs | |
parent | 86e0292733d6d08bf338b68fd50863aef17b1e44 (diff) |
refactor: move PackageJson to deno_config (#24348)
Diffstat (limited to 'cli/npm/byonm.rs')
-rw-r--r-- | cli/npm/byonm.rs | 152 |
1 files changed, 88 insertions, 64 deletions
diff --git a/cli/npm/byonm.rs b/cli/npm/byonm.rs index ec3fb00e9..0d4b9d4d4 100644 --- a/cli/npm/byonm.rs +++ b/cli/npm/byonm.rs @@ -3,7 +3,6 @@ use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; -use std::rc::Rc; use std::sync::Arc; use deno_ast::ModuleSpecifier; @@ -11,12 +10,12 @@ use deno_core::anyhow::bail; use deno_core::error::AnyError; use deno_core::serde_json; use deno_runtime::deno_fs::FileSystem; +use deno_runtime::deno_node::load_pkg_json; use deno_runtime::deno_node::NodePermissions; use deno_runtime::deno_node::NpmResolver; use deno_runtime::deno_node::PackageJson; use deno_semver::package::PackageReq; -use crate::args::package_json::get_local_package_json_version_reqs; use crate::args::NpmProcessState; use crate::args::NpmProcessStateKind; use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs; @@ -51,13 +50,13 @@ impl ByonmCliNpmResolver { &self, dep_name: &str, referrer: &ModuleSpecifier, - ) -> Option<Rc<PackageJson>> { + ) -> Option<Arc<PackageJson>> { let referrer_path = referrer.to_file_path().ok()?; let mut current_folder = referrer_path.parent()?; loop { let pkg_json_path = current_folder.join("package.json"); - if let Ok(pkg_json) = - PackageJson::load_skip_read_permission(self.fs.as_ref(), pkg_json_path) + if let Ok(Some(pkg_json)) = + load_pkg_json(self.fs.as_ref(), &pkg_json_path) { if let Some(deps) = &pkg_json.dependencies { if deps.contains_key(dep_name) { @@ -78,6 +77,70 @@ impl ByonmCliNpmResolver { } } } + + fn resolve_pkg_json_and_alias_for_req( + &self, + req: &PackageReq, + referrer: &ModuleSpecifier, + ) -> Result<(Arc<PackageJson>, String), AnyError> { + fn resolve_alias_from_pkg_json( + req: &PackageReq, + pkg_json: &PackageJson, + ) -> Option<String> { + let deps = pkg_json.resolve_local_package_json_version_reqs(); + for (key, value) in deps { + if let Ok(value) = value { + if value.name == req.name + && value.version_req.intersects(&req.version_req) + { + return Some(key); + } + } + } + None + } + + // attempt to resolve the npm specifier from the referrer's package.json, + if let Ok(file_path) = specifier_to_file_path(referrer) { + let mut current_path = file_path.as_path(); + while let Some(dir_path) = current_path.parent() { + let package_json_path = dir_path.join("package.json"); + if let Some(pkg_json) = + load_pkg_json(self.fs.as_ref(), &package_json_path)? + { + if let Some(alias) = + resolve_alias_from_pkg_json(req, pkg_json.as_ref()) + { + return Ok((pkg_json, alias)); + } + } + current_path = dir_path; + } + } + + // otherwise, fall fallback to the project's package.json + let root_pkg_json_path = self + .root_node_modules_dir + .parent() + .unwrap() + .join("package.json"); + if let Some(pkg_json) = + load_pkg_json(self.fs.as_ref(), &root_pkg_json_path)? + { + if let Some(alias) = resolve_alias_from_pkg_json(req, pkg_json.as_ref()) { + return Ok((pkg_json, alias)); + } + } + + bail!( + concat!( + "Could not find a matching package for 'npm:{}' in a package.json file. ", + "You must specify this as a package.json dependency when the ", + "node_modules folder is not managed by Deno.", + ), + req, + ); + } } impl NpmResolver for ByonmCliNpmResolver { @@ -181,68 +244,29 @@ impl CliNpmResolver for ByonmCliNpmResolver { req: &PackageReq, referrer: &ModuleSpecifier, ) -> Result<PathBuf, AnyError> { - fn resolve_from_package_json( - req: &PackageReq, - fs: &dyn FileSystem, - path: PathBuf, - ) -> Result<PathBuf, AnyError> { - let package_json = PackageJson::load_skip_read_permission(fs, path)?; - let deps = get_local_package_json_version_reqs(&package_json); - for (key, value) in deps { - if let Ok(value) = value { - if value.name == req.name - && value.version_req.intersects(&req.version_req) - { - let package_path = package_json - .path - .parent() - .unwrap() - .join("node_modules") - .join(key); - return Ok(canonicalize_path_maybe_not_exists_with_fs( - &package_path, - fs, - )?); - } - } - } - bail!( - concat!( - "Could not find a matching package for 'npm:{}' in '{}'. ", - "You must specify this as a package.json dependency when the ", - "node_modules folder is not managed by Deno.", - ), - req, - package_json.path.display() - ); - } - - // attempt to resolve the npm specifier from the referrer's package.json, - // but otherwise fallback to the project's package.json - if let Ok(file_path) = specifier_to_file_path(referrer) { - let mut current_path = file_path.as_path(); - while let Some(dir_path) = current_path.parent() { - let package_json_path = dir_path.join("package.json"); - if self.fs.exists_sync(&package_json_path) { - return resolve_from_package_json( - req, - self.fs.as_ref(), - package_json_path, - ); - } - current_path = dir_path; + // resolve the pkg json and alias + let (pkg_json, alias) = + self.resolve_pkg_json_and_alias_for_req(req, referrer)?; + // now try node resolution + for ancestor in pkg_json.path.parent().unwrap().ancestors() { + let node_modules_folder = ancestor.join("node_modules"); + let sub_dir = join_package_name(&node_modules_folder, &alias); + if self.fs.is_dir_sync(&sub_dir) { + return Ok(canonicalize_path_maybe_not_exists_with_fs( + &sub_dir, + self.fs.as_ref(), + )?); } } - resolve_from_package_json( - req, - self.fs.as_ref(), - self - .root_node_modules_dir - .parent() - .unwrap() - .join("package.json"), - ) + bail!( + concat!( + "Could not find \"{}\" in a node_modules folder. ", + "Deno expects the node_modules/ directory to be up to date. ", + "Did you forget to run `npm install`?" + ), + alias, + ); } fn check_state_hash(&self) -> Option<u64> { |