diff options
author | Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> | 2024-08-21 15:23:32 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-21 15:23:32 -0700 |
commit | 48da3c17ea905f50b82948e6f94795e1589f852e (patch) | |
tree | e65d5da97ef0cd4b9f67972b8ba647420d39952e /cli/tools/registry | |
parent | 9aaad3064a412b24e88e308750e038d4e1df6f3c (diff) |
fix(add): Handle packages without root exports (#25102)
Fixes #24607.
This PR makes the logic that caches top level dependencies (things
present in import map) smarter, so we handle JSR dependencies without
root exports.
Diffstat (limited to 'cli/tools/registry')
-rw-r--r-- | cli/tools/registry/mod.rs | 2 | ||||
-rw-r--r-- | cli/tools/registry/pm.rs | 25 | ||||
-rw-r--r-- | cli/tools/registry/pm/cache_deps.rs | 115 |
3 files changed, 133 insertions, 9 deletions
diff --git a/cli/tools/registry/mod.rs b/cli/tools/registry/mod.rs index d6e06fb58..ee3204dc7 100644 --- a/cli/tools/registry/mod.rs +++ b/cli/tools/registry/mod.rs @@ -52,6 +52,7 @@ use crate::util::display::human_size; mod api; mod auth; + mod diagnostics; mod graph; mod paths; @@ -64,6 +65,7 @@ mod unfurl; use auth::get_auth_method; use auth::AuthMethod; pub use pm::add; +pub use pm::cache_top_level_deps; pub use pm::remove; pub use pm::AddCommandName; use publish_order::PublishOrderGraph; diff --git a/cli/tools/registry/pm.rs b/cli/tools/registry/pm.rs index 3cdef071f..87a5ea69a 100644 --- a/cli/tools/registry/pm.rs +++ b/cli/tools/registry/pm.rs @@ -1,5 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +mod cache_deps; + +pub use cache_deps::cache_top_level_deps; + use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; @@ -236,13 +240,16 @@ pub async fn add( let package_futures = package_reqs .into_iter() - .map(move |package_req| { - find_package_and_select_version_for_req( - jsr_resolver.clone(), - npm_resolver.clone(), - package_req, - ) - .boxed_local() + .map({ + let jsr_resolver = jsr_resolver.clone(); + move |package_req| { + find_package_and_select_version_for_req( + jsr_resolver.clone(), + npm_resolver.clone(), + package_req, + ) + .boxed_local() + } }) .collect::<Vec<_>>(); @@ -350,7 +357,7 @@ pub async fn add( // make a new CliFactory to pick up the updated config file let cli_factory = CliFactory::from_flags(flags); // cache deps - crate::module_loader::load_top_level_deps(&cli_factory).await?; + cache_deps::cache_top_level_deps(&cli_factory, Some(jsr_resolver)).await?; Ok(()) } @@ -597,7 +604,7 @@ pub async fn remove( // Update deno.lock node_resolver::PackageJsonThreadLocalCache::clear(); let cli_factory = CliFactory::from_flags(flags); - crate::module_loader::load_top_level_deps(&cli_factory).await?; + cache_deps::cache_top_level_deps(&cli_factory, None).await?; } Ok(()) diff --git a/cli/tools/registry/pm/cache_deps.rs b/cli/tools/registry/pm/cache_deps.rs new file mode 100644 index 000000000..d292c32f5 --- /dev/null +++ b/cli/tools/registry/pm/cache_deps.rs @@ -0,0 +1,115 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::sync::Arc; + +use crate::factory::CliFactory; +use crate::graph_container::ModuleGraphContainer; +use crate::graph_container::ModuleGraphUpdatePermit; +use deno_core::error::AnyError; +use deno_core::futures::stream::FuturesUnordered; +use deno_core::futures::StreamExt; +use deno_semver::package::PackageReq; + +pub async fn cache_top_level_deps( + factory: &CliFactory, + jsr_resolver: Option<Arc<crate::jsr::JsrFetchResolver>>, +) -> Result<(), AnyError> { + let npm_resolver = factory.npm_resolver().await?; + let cli_options = factory.cli_options()?; + if let Some(npm_resolver) = npm_resolver.as_managed() { + if !npm_resolver.ensure_top_level_package_json_install().await? { + if let Some(lockfile) = cli_options.maybe_lockfile() { + lockfile.error_if_changed()?; + } + + npm_resolver.cache_packages().await?; + } + } + // cache as many entries in the import map as we can + let resolver = factory.workspace_resolver().await?; + if let Some(import_map) = resolver.maybe_import_map() { + let jsr_resolver = if let Some(resolver) = jsr_resolver { + resolver + } else { + Arc::new(crate::jsr::JsrFetchResolver::new( + factory.file_fetcher()?.clone(), + )) + }; + + let mut roots = Vec::new(); + + let mut info_futures = FuturesUnordered::new(); + + let mut seen_reqs = std::collections::HashSet::new(); + + for entry in import_map.imports().entries() { + let Some(specifier) = entry.value else { + continue; + }; + + match specifier.scheme() { + "jsr" => { + let specifier_str = specifier.as_str(); + let specifier_str = + specifier_str.strip_prefix("jsr:").unwrap_or(specifier_str); + if let Ok(req) = PackageReq::from_str(specifier_str) { + if !seen_reqs.insert(req.clone()) { + continue; + } + let jsr_resolver = jsr_resolver.clone(); + info_futures.push(async move { + if let Some(nv) = jsr_resolver.req_to_nv(&req).await { + if let Some(info) = jsr_resolver.package_version_info(&nv).await + { + return Some((specifier.clone(), info)); + } + } + None + }); + } + } + "npm" => roots.push(specifier.clone()), + _ => { + if entry.key.ends_with('/') && specifier.as_str().ends_with('/') { + continue; + } + roots.push(specifier.clone()); + } + } + } + + while let Some(info_future) = info_futures.next().await { + if let Some((specifier, info)) = info_future { + if info.export(".").is_some() { + roots.push(specifier.clone()); + continue; + } + let exports = info.exports(); + for (k, _) in exports { + if let Ok(spec) = specifier.join(k) { + roots.push(spec); + } + } + } + } + let mut graph_permit = factory + .main_module_graph_container() + .await? + .acquire_update_permit() + .await; + let graph = graph_permit.graph_mut(); + factory + .module_load_preparer() + .await? + .prepare_module_load( + graph, + &roots, + false, + deno_config::deno_json::TsTypeLib::DenoWorker, + deno_runtime::deno_permissions::PermissionsContainer::allow_all(), + ) + .await?; + } + + Ok(()) +} |