summaryrefslogtreecommitdiff
path: root/cli/npm/managed/resolvers/global.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-09-30 12:06:38 -0400
committerGitHub <noreply@github.com>2023-09-30 12:06:38 -0400
commit8d24be1a59714761665516e0d78d25059608c29b (patch)
treeaed0140b63441008cb9b549d44948f7a36a4f5f1 /cli/npm/managed/resolvers/global.rs
parent1cda3840ff673512f7c6d58fa8402c35c760bc3b (diff)
refactor(npm): create `cli::npm::managed` module (#20740)
Creates the `cli::npm::managed` module and starts moving more functionality into it.
Diffstat (limited to 'cli/npm/managed/resolvers/global.rs')
-rw-r--r--cli/npm/managed/resolvers/global.rs184
1 files changed, 184 insertions, 0 deletions
diff --git a/cli/npm/managed/resolvers/global.rs b/cli/npm/managed/resolvers/global.rs
new file mode 100644
index 000000000..25db62f73
--- /dev/null
+++ b/cli/npm/managed/resolvers/global.rs
@@ -0,0 +1,184 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+
+//! Code for global npm cache resolution.
+
+use std::path::Path;
+use std::path::PathBuf;
+use std::sync::Arc;
+
+use async_trait::async_trait;
+use deno_ast::ModuleSpecifier;
+use deno_core::anyhow::bail;
+use deno_core::error::AnyError;
+use deno_core::url::Url;
+use deno_npm::resolution::PackageNotFoundFromReferrerError;
+use deno_npm::NpmPackageCacheFolderId;
+use deno_npm::NpmPackageId;
+use deno_npm::NpmResolutionPackage;
+use deno_npm::NpmSystemInfo;
+use deno_runtime::deno_fs::FileSystem;
+use deno_runtime::deno_node::NodePermissions;
+use deno_runtime::deno_node::NodeResolutionMode;
+
+use crate::npm::NpmCache;
+
+use super::super::resolution::NpmResolution;
+use super::common::cache_packages;
+use super::common::types_package_name;
+use super::common::NpmPackageFsResolver;
+use super::common::RegistryReadPermissionChecker;
+
+/// Resolves packages from the global npm cache.
+#[derive(Debug)]
+pub struct GlobalNpmPackageResolver {
+ cache: Arc<NpmCache>,
+ resolution: Arc<NpmResolution>,
+ registry_url: Url,
+ system_info: NpmSystemInfo,
+ registry_read_permission_checker: RegistryReadPermissionChecker,
+}
+
+impl GlobalNpmPackageResolver {
+ pub fn new(
+ fs: Arc<dyn FileSystem>,
+ cache: Arc<NpmCache>,
+ registry_url: Url,
+ resolution: Arc<NpmResolution>,
+ system_info: NpmSystemInfo,
+ ) -> Self {
+ Self {
+ cache: cache.clone(),
+ resolution,
+ registry_url: registry_url.clone(),
+ system_info,
+ registry_read_permission_checker: RegistryReadPermissionChecker::new(
+ fs,
+ cache.registry_folder(&registry_url),
+ ),
+ }
+ }
+
+ fn resolve_types_package(
+ &self,
+ package_name: &str,
+ referrer_pkg_id: &NpmPackageCacheFolderId,
+ ) -> Result<NpmResolutionPackage, Box<PackageNotFoundFromReferrerError>> {
+ let types_name = types_package_name(package_name);
+ self
+ .resolution
+ .resolve_package_from_package(&types_name, referrer_pkg_id)
+ }
+}
+
+#[async_trait]
+impl NpmPackageFsResolver for GlobalNpmPackageResolver {
+ fn root_dir_url(&self) -> &Url {
+ self.cache.root_dir_url()
+ }
+
+ fn node_modules_path(&self) -> Option<PathBuf> {
+ None
+ }
+
+ fn package_folder(&self, id: &NpmPackageId) -> Result<PathBuf, AnyError> {
+ let folder_id = self
+ .resolution
+ .resolve_pkg_cache_folder_id_from_pkg_id(id)
+ .unwrap();
+ Ok(
+ self
+ .cache
+ .package_folder_for_id(&folder_id, &self.registry_url),
+ )
+ }
+
+ fn resolve_package_folder_from_package(
+ &self,
+ name: &str,
+ referrer: &ModuleSpecifier,
+ mode: NodeResolutionMode,
+ ) -> Result<PathBuf, AnyError> {
+ let Some(referrer_pkg_id) = self
+ .cache
+ .resolve_package_folder_id_from_specifier(referrer, &self.registry_url)
+ else {
+ bail!("could not find npm package for '{}'", referrer);
+ };
+ let pkg = if mode.is_types() && !name.starts_with("@types/") {
+ // attempt to resolve the types package first, then fallback to the regular package
+ match self.resolve_types_package(name, &referrer_pkg_id) {
+ Ok(pkg) => pkg,
+ Err(_) => self
+ .resolution
+ .resolve_package_from_package(name, &referrer_pkg_id)?,
+ }
+ } else {
+ self
+ .resolution
+ .resolve_package_from_package(name, &referrer_pkg_id)?
+ };
+ self.package_folder(&pkg.id)
+ }
+
+ fn resolve_package_folder_from_specifier(
+ &self,
+ specifier: &ModuleSpecifier,
+ ) -> Result<Option<PathBuf>, AnyError> {
+ let Some(pkg_folder_id) = self
+ .cache
+ .resolve_package_folder_id_from_specifier(specifier, &self.registry_url)
+ else {
+ return Ok(None);
+ };
+ Ok(Some(
+ self
+ .cache
+ .package_folder_for_id(&pkg_folder_id, &self.registry_url),
+ ))
+ }
+
+ fn resolve_package_cache_folder_id_from_specifier(
+ &self,
+ specifier: &ModuleSpecifier,
+ ) -> Result<Option<NpmPackageCacheFolderId>, AnyError> {
+ Ok(
+ self.cache.resolve_package_folder_id_from_specifier(
+ specifier,
+ &self.registry_url,
+ ),
+ )
+ }
+
+ async fn cache_packages(&self) -> Result<(), AnyError> {
+ let package_partitions = self
+ .resolution
+ .all_system_packages_partitioned(&self.system_info);
+
+ cache_packages(
+ package_partitions.packages,
+ &self.cache,
+ &self.registry_url,
+ )
+ .await?;
+
+ // create the copy package folders
+ for copy in package_partitions.copy_packages {
+ self.cache.ensure_copy_package(
+ &copy.get_package_cache_folder_id(),
+ &self.registry_url,
+ )?;
+ }
+
+ Ok(())
+ }
+
+ fn ensure_read_permission(
+ &self,
+ permissions: &dyn NodePermissions,
+ path: &Path,
+ ) -> Result<(), AnyError> {
+ self
+ .registry_read_permission_checker
+ .ensure_registry_read_permission(permissions, path)
+ }
+}