summaryrefslogtreecommitdiff
path: root/cli/resolver.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-02-23 12:33:23 -0500
committerGitHub <noreply@github.com>2023-02-23 17:33:23 +0000
commit6233c0aff0dc9e58b02dfc9499048385bbf836c6 (patch)
treeb6f09c73bbaca669e22b5f5c6f30961a87f78be5 /cli/resolver.rs
parent344317ec501fa124f0c74b44035fa4516999dce6 (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.rs89
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);
+ }
+}