summaryrefslogtreecommitdiff
path: root/cli/npm/byonm.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-06-26 17:24:10 -0400
committerGitHub <noreply@github.com>2024-06-26 21:24:10 +0000
commit0da01c0ca6b537f74be32126e567bdfc2c73ed16 (patch)
treeef29d32cffb03a975a58c16827b0691dda50a5b3 /cli/npm/byonm.rs
parent86e0292733d6d08bf338b68fd50863aef17b1e44 (diff)
refactor: move PackageJson to deno_config (#24348)
Diffstat (limited to 'cli/npm/byonm.rs')
-rw-r--r--cli/npm/byonm.rs152
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> {