diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-02-23 12:33:23 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-23 17:33:23 +0000 |
commit | 6233c0aff0dc9e58b02dfc9499048385bbf836c6 (patch) | |
tree | b6f09c73bbaca669e22b5f5c6f30961a87f78be5 /cli/resolver.rs | |
parent | 344317ec501fa124f0c74b44035fa4516999dce6 (diff) |
fix(npm): support bare specifiers in package.json having a path (#17903)
For example `import * as test from "package/path.js"`
Diffstat (limited to 'cli/resolver.rs')
-rw-r--r-- | cli/resolver.rs | 89 |
1 files changed, 86 insertions, 3 deletions
diff --git a/cli/resolver.rs b/cli/resolver.rs index ce0d5d5cf..db6ef0c8e 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -14,7 +14,7 @@ use deno_graph::source::UnknownBuiltInNodeModuleError; use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE; use deno_runtime::deno_node::is_builtin_node_module; use import_map::ImportMap; -use std::collections::HashMap; +use std::collections::BTreeMap; use std::sync::Arc; use crate::args::JsxImportSourceConfig; @@ -26,7 +26,7 @@ use crate::npm::NpmResolution; #[derive(Debug, Clone)] pub struct CliGraphResolver { maybe_import_map: Option<Arc<ImportMap>>, - maybe_package_json_deps: Option<HashMap<String, NpmPackageReq>>, + maybe_package_json_deps: Option<BTreeMap<String, NpmPackageReq>>, maybe_default_jsx_import_source: Option<String>, maybe_jsx_import_source_module: Option<String>, no_npm: bool, @@ -62,7 +62,7 @@ impl CliGraphResolver { no_npm: bool, npm_registry_api: NpmRegistryApi, npm_resolution: NpmResolution, - maybe_package_json_deps: Option<HashMap<String, NpmPackageReq>>, + maybe_package_json_deps: Option<BTreeMap<String, NpmPackageReq>>, ) -> Self { Self { maybe_import_map, @@ -120,6 +120,9 @@ impl Resolver for CliGraphResolver { } if let Some(deps) = self.maybe_package_json_deps.as_ref() { + if let Some(specifier) = resolve_package_json_dep(specifier, deps)? { + return Ok(specifier); + } if let Some(req) = deps.get(specifier) { return Ok(ModuleSpecifier::parse(&format!("npm:{req}")).unwrap()); } @@ -129,6 +132,25 @@ impl Resolver for CliGraphResolver { } } +fn resolve_package_json_dep( + specifier: &str, + deps: &BTreeMap<String, NpmPackageReq>, +) -> Result<Option<ModuleSpecifier>, deno_core::url::ParseError> { + for (bare_specifier, req) in deps { + if specifier.starts_with(bare_specifier) { + if specifier.len() == bare_specifier.len() { + return ModuleSpecifier::parse(&format!("npm:{req}")).map(Some); + } + let path = &specifier[bare_specifier.len()..]; + if path.starts_with('/') { + return ModuleSpecifier::parse(&format!("npm:/{req}{path}")).map(Some); + } + } + } + + Ok(None) +} + impl NpmResolver for CliGraphResolver { fn resolve_builtin_node_module( &self, @@ -184,3 +206,64 @@ impl NpmResolver for CliGraphResolver { .resolve_package_req_for_deno_graph(package_req) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_resolve_package_json_dep() { + fn resolve( + specifier: &str, + deps: &BTreeMap<String, NpmPackageReq>, + ) -> Result<Option<String>, String> { + resolve_package_json_dep(specifier, deps) + .map(|s| s.map(|s| s.to_string())) + .map_err(|err| err.to_string()) + } + + let deps = BTreeMap::from([ + ( + "package".to_string(), + NpmPackageReq::from_str("package@1.0").unwrap(), + ), + ( + "package-alias".to_string(), + NpmPackageReq::from_str("package@^1.2").unwrap(), + ), + ( + "@deno/test".to_string(), + NpmPackageReq::from_str("@deno/test@~0.2").unwrap(), + ), + ]); + + assert_eq!( + resolve("package", &deps).unwrap(), + Some("npm:package@1.0".to_string()), + ); + assert_eq!( + resolve("package/some_path.ts", &deps).unwrap(), + Some("npm:/package@1.0/some_path.ts".to_string()), + ); + + assert_eq!( + resolve("@deno/test", &deps).unwrap(), + Some("npm:@deno/test@~0.2".to_string()), + ); + assert_eq!( + resolve("@deno/test/some_path.ts", &deps).unwrap(), + Some("npm:/@deno/test@~0.2/some_path.ts".to_string()), + ); + // matches the start, but doesn't have the same length or a path + assert_eq!(resolve("@deno/testing", &deps).unwrap(), None,); + + // alias + assert_eq!( + resolve("package-alias", &deps).unwrap(), + Some("npm:package@^1.2".to_string()), + ); + + // non-existent bare specifier + assert_eq!(resolve("non-existent", &deps).unwrap(), None); + } +} |