summaryrefslogtreecommitdiff
path: root/ext/node/resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/resolution.rs')
-rw-r--r--ext/node/resolution.rs288
1 files changed, 161 insertions, 127 deletions
diff --git a/ext/node/resolution.rs b/ext/node/resolution.rs
index dc247ddce..dd89dc1fd 100644
--- a/ext/node/resolution.rs
+++ b/ext/node/resolution.rs
@@ -15,10 +15,6 @@ use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use deno_fs::FileSystemRc;
use deno_media_type::MediaType;
-use deno_semver::npm::NpmPackageNvReference;
-use deno_semver::npm::NpmPackageReqReference;
-use deno_semver::package::PackageNv;
-use deno_semver::package::PackageNvReference;
use crate::errors;
use crate::AllowAllNodePermissions;
@@ -329,46 +325,30 @@ impl NodeResolver {
Ok(resolved)
}
- pub fn resolve_npm_req_reference(
- &self,
- reference: &NpmPackageReqReference,
- mode: NodeResolutionMode,
- permissions: &dyn NodePermissions,
- ) -> Result<Option<NodeResolution>, AnyError> {
- let pkg_id = self
- .npm_resolver
- .resolve_pkg_id_from_pkg_req(reference.req())?;
- let reference = NpmPackageNvReference::new(PackageNvReference {
- nv: pkg_id.nv,
- sub_path: reference.sub_path().map(ToOwned::to_owned),
- });
- self.resolve_npm_reference(&reference, mode, permissions)
- }
-
pub fn resolve_npm_reference(
&self,
- reference: &NpmPackageNvReference,
+ package_folder: &Path,
+ sub_path: Option<&str>,
mode: NodeResolutionMode,
permissions: &dyn NodePermissions,
) -> Result<Option<NodeResolution>, AnyError> {
- let package_folder = self
- .npm_resolver
- .resolve_package_folder_from_deno_module(reference.nv())?;
let node_module_kind = NodeModuleKind::Esm;
let maybe_resolved_path = self
.package_config_resolve(
- &reference
- .sub_path()
+ &sub_path
.map(|s| format!("./{s}"))
.unwrap_or_else(|| ".".to_string()),
- &package_folder,
+ package_folder,
node_module_kind,
DEFAULT_CONDITIONS,
mode,
permissions,
)
.with_context(|| {
- format!("Failed resolving package config for '{reference}'")
+ format!(
+ "Failed resolving package config for '{}'",
+ package_folder.join("package.json").display()
+ )
})?;
let resolved_path = match maybe_resolved_path {
Some(resolved_path) => resolved_path,
@@ -392,17 +372,19 @@ impl NodeResolver {
pub fn resolve_binary_commands(
&self,
- pkg_nv: &PackageNv,
+ package_folder: &Path,
) -> Result<Vec<String>, AnyError> {
- let package_folder = self
- .npm_resolver
- .resolve_package_folder_from_deno_module(pkg_nv)?;
let package_json_path = package_folder.join("package.json");
- let package_json =
- self.load_package_json(&AllowAllNodePermissions, package_json_path)?;
+ let package_json = self
+ .load_package_json(&AllowAllNodePermissions, package_json_path.clone())?;
Ok(match package_json.bin {
- Some(Value::String(_)) => vec![pkg_nv.name.to_string()],
+ Some(Value::String(_)) => {
+ let Some(name) = &package_json.name else {
+ bail!("'{}' did not have a name", package_json_path.display());
+ };
+ vec![name.to_string()]
+ }
Some(Value::Object(o)) => {
o.into_iter().map(|(key, _)| key).collect::<Vec<_>>()
}
@@ -412,27 +394,13 @@ impl NodeResolver {
pub fn resolve_binary_export(
&self,
- pkg_ref: &NpmPackageReqReference,
+ package_folder: &Path,
+ sub_path: Option<&str>,
) -> Result<NodeResolution, AnyError> {
- let pkg_nv = self
- .npm_resolver
- .resolve_pkg_id_from_pkg_req(pkg_ref.req())?
- .nv;
- let bin_name = pkg_ref.sub_path();
- let package_folder = self
- .npm_resolver
- .resolve_package_folder_from_deno_module(&pkg_nv)?;
let package_json_path = package_folder.join("package.json");
- let package_json =
- self.load_package_json(&AllowAllNodePermissions, package_json_path)?;
- let bin = match &package_json.bin {
- Some(bin) => bin,
- None => bail!(
- "package '{}' did not have a bin property in its package.json",
- &pkg_nv.name,
- ),
- };
- let bin_entry = resolve_bin_entry_value(&pkg_nv, bin_name, bin)?;
+ let package_json = self
+ .load_package_json(&AllowAllNodePermissions, package_json_path.clone())?;
+ let bin_entry = resolve_bin_entry_value(&package_json, sub_path)?;
let url =
ModuleSpecifier::from_file_path(package_folder.join(bin_entry)).unwrap();
@@ -1293,13 +1261,19 @@ impl NodeResolver {
}
fn resolve_bin_entry_value<'a>(
- pkg_nv: &PackageNv,
+ package_json: &'a PackageJson,
bin_name: Option<&str>,
- bin: &'a Value,
) -> Result<&'a str, AnyError> {
+ let bin = match &package_json.bin {
+ Some(bin) => bin,
+ None => bail!(
+ "'{}' did not have a bin property",
+ package_json.path.display(),
+ ),
+ };
let bin_entry = match bin {
Value::String(_) => {
- if bin_name.is_some() && bin_name.unwrap() != pkg_nv.name {
+ if bin_name.is_some() && bin_name != package_json.name.as_deref() {
None
} else {
Some(bin)
@@ -1308,29 +1282,50 @@ fn resolve_bin_entry_value<'a>(
Value::Object(o) => {
if let Some(bin_name) = bin_name {
o.get(bin_name)
- } else if o.len() == 1 || o.len() > 1 && o.values().all(|v| v == o.values().next().unwrap()) {
+ } else if o.len() == 1
+ || o.len() > 1 && o.values().all(|v| v == o.values().next().unwrap())
+ {
o.values().next()
} else {
- o.get(&pkg_nv.name)
+ package_json.name.as_ref().and_then(|n| o.get(n))
}
- },
- _ => bail!("package '{}' did not have a bin property with a string or object value in its package.json", pkg_nv),
+ }
+ _ => bail!(
+ "'{}' did not have a bin property with a string or object value",
+ package_json.path.display()
+ ),
};
let bin_entry = match bin_entry {
Some(e) => e,
None => {
+ let prefix = package_json
+ .name
+ .as_ref()
+ .map(|n| {
+ let mut prefix = format!("npm:{}", n);
+ if let Some(version) = &package_json.version {
+ prefix.push('@');
+ prefix.push_str(version);
+ }
+ prefix.push('/');
+ prefix
+ })
+ .unwrap_or_default();
let keys = bin
.as_object()
.map(|o| {
o.keys()
- .map(|k| format!(" * npm:{pkg_nv}/{k}"))
+ .map(|k| format!(" * {prefix}{k}"))
.collect::<Vec<_>>()
})
.unwrap_or_default();
bail!(
- "package '{}' did not have a bin entry for '{}' in its package.json{}",
- pkg_nv,
- bin_name.unwrap_or(&pkg_nv.name),
+ "'{}' did not have a bin entry{}{}",
+ package_json.path.display(),
+ bin_name
+ .or(package_json.name.as_deref())
+ .map(|name| format!(" for '{}'", name))
+ .unwrap_or_default(),
if keys.is_empty() {
"".to_string()
} else {
@@ -1342,8 +1337,8 @@ fn resolve_bin_entry_value<'a>(
match bin_entry {
Value::String(s) => Ok(s),
_ => bail!(
- "package '{}' had a non-string sub property of bin in its package.json",
- pkg_nv,
+ "'{}' had a non-string sub property of bin",
+ package_json.path.display(),
),
}
}
@@ -1595,102 +1590,141 @@ mod tests {
use super::*;
+ fn build_package_json(json: Value) -> PackageJson {
+ PackageJson::load_from_value(PathBuf::from("/package.json"), json).unwrap()
+ }
+
#[test]
fn test_resolve_bin_entry_value() {
// should resolve the specified value
- let value = json!({
- "bin1": "./value1",
- "bin2": "./value2",
- "test": "./value3",
- });
+ let pkg_json = build_package_json(json!({
+ "name": "pkg",
+ "version": "1.1.1",
+ "bin": {
+ "bin1": "./value1",
+ "bin2": "./value2",
+ "pkg": "./value3",
+ }
+ }));
assert_eq!(
- resolve_bin_entry_value(
- &PackageNv::from_str("test@1.1.1").unwrap(),
- Some("bin1"),
- &value
- )
- .unwrap(),
+ resolve_bin_entry_value(&pkg_json, Some("bin1")).unwrap(),
"./value1"
);
// should resolve the value with the same name when not specified
assert_eq!(
- resolve_bin_entry_value(
- &PackageNv::from_str("test@1.1.1").unwrap(),
- None,
- &value
- )
- .unwrap(),
+ resolve_bin_entry_value(&pkg_json, None).unwrap(),
"./value3"
);
// should not resolve when specified value does not exist
assert_eq!(
- resolve_bin_entry_value(
- &PackageNv::from_str("test@1.1.1").unwrap(),
- Some("other"),
- &value
- )
- .err()
- .unwrap()
- .to_string(),
+ resolve_bin_entry_value(&pkg_json, Some("other"),)
+ .err()
+ .unwrap()
+ .to_string(),
concat!(
- "package 'test@1.1.1' did not have a bin entry for 'other' in its package.json\n",
+ "'/package.json' did not have a bin entry for 'other'\n",
"\n",
"Possibilities:\n",
- " * npm:test@1.1.1/bin1\n",
- " * npm:test@1.1.1/bin2\n",
- " * npm:test@1.1.1/test"
+ " * npm:pkg@1.1.1/bin1\n",
+ " * npm:pkg@1.1.1/bin2\n",
+ " * npm:pkg@1.1.1/pkg"
)
);
// should not resolve when default value can't be determined
+ let pkg_json = build_package_json(json!({
+ "name": "pkg",
+ "version": "1.1.1",
+ "bin": {
+ "bin": "./value1",
+ "bin2": "./value2",
+ }
+ }));
assert_eq!(
- resolve_bin_entry_value(
- &PackageNv::from_str("asdf@1.2.3").unwrap(),
- None,
- &value
- )
- .err()
- .unwrap()
- .to_string(),
+ resolve_bin_entry_value(&pkg_json, None)
+ .err()
+ .unwrap()
+ .to_string(),
concat!(
- "package 'asdf@1.2.3' did not have a bin entry for 'asdf' in its package.json\n",
+ "'/package.json' did not have a bin entry for 'pkg'\n",
"\n",
"Possibilities:\n",
- " * npm:asdf@1.2.3/bin1\n",
- " * npm:asdf@1.2.3/bin2\n",
- " * npm:asdf@1.2.3/test"
+ " * npm:pkg@1.1.1/bin\n",
+ " * npm:pkg@1.1.1/bin2",
)
);
// should resolve since all the values are the same
- let value = json!({
- "bin1": "./value",
- "bin2": "./value",
- });
+ let pkg_json = build_package_json(json!({
+ "name": "pkg",
+ "version": "1.2.3",
+ "bin": {
+ "bin1": "./value",
+ "bin2": "./value",
+ }
+ }));
assert_eq!(
- resolve_bin_entry_value(
- &PackageNv::from_str("test@1.2.3").unwrap(),
- None,
- &value
- )
- .unwrap(),
+ resolve_bin_entry_value(&pkg_json, None,).unwrap(),
"./value"
);
// should not resolve when specified and is a string
- let value = json!("./value");
+ let pkg_json = build_package_json(json!({
+ "name": "pkg",
+ "version": "1.2.3",
+ "bin": "./value",
+ }));
+ assert_eq!(
+ resolve_bin_entry_value(&pkg_json, Some("path"),)
+ .err()
+ .unwrap()
+ .to_string(),
+ "'/package.json' did not have a bin entry for 'path'"
+ );
+
+ // no version in the package.json
+ let pkg_json = build_package_json(json!({
+ "name": "pkg",
+ "bin": {
+ "bin1": "./value1",
+ "bin2": "./value2",
+ }
+ }));
+ assert_eq!(
+ resolve_bin_entry_value(&pkg_json, None)
+ .err()
+ .unwrap()
+ .to_string(),
+ concat!(
+ "'/package.json' did not have a bin entry for 'pkg'\n",
+ "\n",
+ "Possibilities:\n",
+ " * npm:pkg/bin1\n",
+ " * npm:pkg/bin2",
+ )
+ );
+
+ // no name or version in the package.json
+ let pkg_json = build_package_json(json!({
+ "bin": {
+ "bin1": "./value1",
+ "bin2": "./value2",
+ }
+ }));
assert_eq!(
- resolve_bin_entry_value(
- &PackageNv::from_str("test@1.2.3").unwrap(),
- Some("path"),
- &value
+ resolve_bin_entry_value(&pkg_json, None)
+ .err()
+ .unwrap()
+ .to_string(),
+ concat!(
+ "'/package.json' did not have a bin entry\n",
+ "\n",
+ "Possibilities:\n",
+ " * bin1\n",
+ " * bin2",
)
- .err()
- .unwrap()
- .to_string(),
- "package 'test@1.2.3' did not have a bin entry for 'path' in its package.json"
);
}