summaryrefslogtreecommitdiff
path: root/cli/npm
diff options
context:
space:
mode:
Diffstat (limited to 'cli/npm')
-rw-r--r--cli/npm/installer.rs88
-rw-r--r--cli/npm/mod.rs2
-rw-r--r--cli/npm/resolution/mod.rs5
-rw-r--r--cli/npm/resolvers/mod.rs14
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,