diff options
Diffstat (limited to 'cli/npm')
-rw-r--r-- | cli/npm/installer.rs | 88 | ||||
-rw-r--r-- | cli/npm/mod.rs | 2 | ||||
-rw-r--r-- | cli/npm/resolution/mod.rs | 5 | ||||
-rw-r--r-- | cli/npm/resolvers/mod.rs | 14 |
4 files changed, 93 insertions, 16 deletions
diff --git a/cli/npm/installer.rs b/cli/npm/installer.rs new file mode 100644 index 000000000..149126cd5 --- /dev/null +++ b/cli/npm/installer.rs @@ -0,0 +1,88 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +use std::collections::BTreeMap; +use std::sync::atomic::AtomicBool; +use std::sync::Arc; + +use deno_core::error::AnyError; +use deno_graph::npm::NpmPackageReq; + +use super::NpmRegistryApi; +use super::NpmResolution; + +#[derive(Debug)] +struct PackageJsonDepsInstallerInner { + has_installed: AtomicBool, + npm_registry_api: NpmRegistryApi, + npm_resolution: NpmResolution, + package_deps: BTreeMap<String, NpmPackageReq>, +} + +/// Holds and controls installing dependencies from package.json. +#[derive(Debug, Clone, Default)] +pub struct PackageJsonDepsInstaller(Option<Arc<PackageJsonDepsInstallerInner>>); + +impl PackageJsonDepsInstaller { + pub fn new( + npm_registry_api: NpmRegistryApi, + npm_resolution: NpmResolution, + deps: Option<BTreeMap<String, NpmPackageReq>>, + ) -> Self { + Self(deps.map(|package_deps| { + Arc::new(PackageJsonDepsInstallerInner { + has_installed: AtomicBool::new(false), + npm_registry_api, + npm_resolution, + package_deps, + }) + })) + } + + pub fn package_deps(&self) -> Option<&BTreeMap<String, NpmPackageReq>> { + self.0.as_ref().map(|inner| &inner.package_deps) + } + + /// Gets if the package.json has the specified package name. + pub fn has_package_name(&self, name: &str) -> bool { + if let Some(package_deps) = self.package_deps() { + // ensure this looks at the package name and not the + // bare specifiers (do not look at the keys!) + package_deps.values().any(|v| v.name == name) + } else { + false + } + } + + /// Installs the top level dependencies in the package.json file + /// without going through and resolving the descendant dependencies yet. + pub async fn ensure_top_level_install(&self) -> Result<(), AnyError> { + use std::sync::atomic::Ordering; + let inner = match &self.0 { + Some(inner) => inner, + None => return Ok(()), + }; + + if inner.has_installed.swap(true, Ordering::SeqCst) { + return Ok(()); // already installed by something else + } + + let mut package_reqs = + inner.package_deps.values().cloned().collect::<Vec<_>>(); + package_reqs.sort(); // deterministic resolution + + inner + .npm_registry_api + .cache_in_parallel( + package_reqs.iter().map(|req| req.name.clone()).collect(), + ) + .await?; + + for package_req in package_reqs { + inner + .npm_resolution + .resolve_package_req_as_pending(&package_req)?; + } + + Ok(()) + } +} diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index 602b4ad44..ea18f8866 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -1,6 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. mod cache; +mod installer; mod registry; mod resolution; mod resolvers; @@ -8,6 +9,7 @@ mod tarball; pub use cache::should_sync_download; pub use cache::NpmCache; +pub use installer::PackageJsonDepsInstaller; #[cfg(test)] pub use registry::NpmPackageVersionDistInfo; pub use registry::NpmRegistryApi; diff --git a/cli/npm/resolution/mod.rs b/cli/npm/resolution/mod.rs index 53284d712..f43f3c5cb 100644 --- a/cli/npm/resolution/mod.rs +++ b/cli/npm/resolution/mod.rs @@ -404,8 +404,9 @@ impl NpmResolution { } /// Resolves a package requirement for deno graph. This should only be - /// called by deno_graph's NpmResolver. - pub fn resolve_package_req_for_deno_graph( + /// called by deno_graph's NpmResolver or for resolving packages in + /// a package.json + pub fn resolve_package_req_as_pending( &self, pkg_req: &NpmPackageReq, ) -> Result<NpmPackageNv, AnyError> { diff --git a/cli/npm/resolvers/mod.rs b/cli/npm/resolvers/mod.rs index f68eeac26..0027698c0 100644 --- a/cli/npm/resolvers/mod.rs +++ b/cli/npm/resolvers/mod.rs @@ -19,7 +19,6 @@ use deno_runtime::deno_node::RequireNpmResolver; use global::GlobalNpmPackageResolver; use serde::Deserialize; use serde::Serialize; -use std::collections::BTreeMap; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; @@ -224,19 +223,6 @@ impl NpmPackageResolver { self.resolution.has_packages() } - /// Adds the package reqs from a package.json if they exist. - pub async fn add_package_json_deps( - &self, - maybe_package_json_deps: Option<&BTreeMap<String, NpmPackageReq>>, - ) -> Result<(), AnyError> { - if let Some(deps) = maybe_package_json_deps { - let mut package_reqs = deps.values().cloned().collect::<Vec<_>>(); - package_reqs.sort(); // deterministic resolution - self.add_package_reqs(package_reqs).await?; - } - Ok(()) - } - /// Adds package requirements to the resolver and ensures everything is setup. pub async fn add_package_reqs( &self, |