diff options
Diffstat (limited to 'cli/npm/resolvers/mod.rs')
-rw-r--r-- | cli/npm/resolvers/mod.rs | 416 |
1 files changed, 0 insertions, 416 deletions
diff --git a/cli/npm/resolvers/mod.rs b/cli/npm/resolvers/mod.rs deleted file mode 100644 index 07a122a3e..000000000 --- a/cli/npm/resolvers/mod.rs +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -mod common; -mod global; -mod local; - -use std::collections::HashMap; -use std::path::Path; -use std::path::PathBuf; -use std::sync::Arc; - -use deno_ast::ModuleSpecifier; -use deno_core::error::AnyError; -use deno_core::parking_lot::Mutex; -use deno_core::serde_json; -use deno_core::url::Url; -use deno_npm::resolution::NpmResolutionSnapshot; -use deno_npm::resolution::PackageReqNotFoundError; -use deno_npm::resolution::SerializedNpmResolutionSnapshot; -use deno_npm::NpmPackageId; -use deno_npm::NpmSystemInfo; -use deno_runtime::deno_fs::FileSystem; -use deno_runtime::deno_node::NodePermissions; -use deno_runtime::deno_node::NodeResolutionMode; -use deno_runtime::deno_node::NpmResolver; -use deno_semver::npm::NpmPackageNvReference; -use deno_semver::npm::NpmPackageReqReference; -use deno_semver::package::PackageNv; -use deno_semver::package::PackageNvReference; -use deno_semver::package::PackageReq; -use global::GlobalNpmPackageResolver; -use serde::Deserialize; -use serde::Serialize; - -use crate::args::Lockfile; -use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs; -use crate::util::progress_bar::ProgressBar; - -use self::local::LocalNpmPackageResolver; -use super::resolution::NpmResolution; -use super::NpmCache; - -pub use self::common::NpmPackageFsResolver; - -/// State provided to the process via an environment variable. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct NpmProcessState { - pub snapshot: SerializedNpmResolutionSnapshot, - pub local_node_modules_path: Option<String>, -} - -pub enum InnerCliNpmResolverRef<'a> { - Managed(&'a ManagedCliNpmResolver), - #[allow(dead_code)] - Byonm(&'a ByonmCliNpmResolver), -} - -pub trait CliNpmResolver: NpmResolver { - fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver>; - - fn root_dir_url(&self) -> &Url; - - fn as_inner(&self) -> InnerCliNpmResolverRef; - - fn as_managed(&self) -> Option<&ManagedCliNpmResolver> { - match self.as_inner() { - InnerCliNpmResolverRef::Managed(inner) => Some(inner), - InnerCliNpmResolverRef::Byonm(_) => None, - } - } - - fn node_modules_path(&self) -> Option<PathBuf>; - - /// Checks if the provided package req's folder is cached. - fn is_pkg_req_folder_cached(&self, req: &PackageReq) -> bool; - - fn resolve_pkg_nv_ref_from_pkg_req_ref( - &self, - req_ref: &NpmPackageReqReference, - ) -> Result<NpmPackageNvReference, PackageReqNotFoundError>; - - /// Resolve the root folder of the package the provided specifier is in. - /// - /// This will error when the provided specifier is not in an npm package. - fn resolve_pkg_folder_from_specifier( - &self, - specifier: &ModuleSpecifier, - ) -> Result<Option<PathBuf>, AnyError>; - - fn resolve_pkg_folder_from_deno_module_req( - &self, - req: &PackageReq, - ) -> Result<PathBuf, AnyError>; - - fn resolve_pkg_folder_from_deno_module( - &self, - nv: &PackageNv, - ) -> Result<PathBuf, AnyError>; - - /// Gets the state of npm for the process. - fn get_npm_process_state(&self) -> String; - - // todo(#18967): should instead return a hash state of the resolver - // or perhaps this could be non-BYONM only and byonm always runs deno check - fn package_reqs(&self) -> HashMap<PackageReq, PackageNv>; -} - -// todo(dsherret): implement this -pub struct ByonmCliNpmResolver; - -/// An npm resolver where the resolution is managed by Deno rather than -/// the user bringing their own node_modules (BYONM) on the file system. -pub struct ManagedCliNpmResolver { - fs: Arc<dyn FileSystem>, - fs_resolver: Arc<dyn NpmPackageFsResolver>, - resolution: Arc<NpmResolution>, - maybe_lockfile: Option<Arc<Mutex<Lockfile>>>, -} - -impl std::fmt::Debug for ManagedCliNpmResolver { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("ManagedNpmResolver") - .field("fs", &"<omitted>") - .field("fs_resolver", &"<omitted>") - .field("resolution", &"<omitted>") - .field("maybe_lockfile", &"<omitted>") - .finish() - } -} - -impl ManagedCliNpmResolver { - pub fn new( - fs: Arc<dyn FileSystem>, - resolution: Arc<NpmResolution>, - fs_resolver: Arc<dyn NpmPackageFsResolver>, - maybe_lockfile: Option<Arc<Mutex<Lockfile>>>, - ) -> Self { - Self { - fs, - fs_resolver, - resolution, - maybe_lockfile, - } - } - - pub fn resolve_pkg_folder_from_pkg_id( - &self, - pkg_id: &NpmPackageId, - ) -> Result<PathBuf, AnyError> { - let path = self.fs_resolver.package_folder(pkg_id)?; - let path = canonicalize_path_maybe_not_exists_with_fs(&path, |path| { - self - .fs - .realpath_sync(path) - .map_err(|err| err.into_io_error()) - })?; - log::debug!( - "Resolved package folder of {} to {}", - pkg_id.as_serialized(), - path.display() - ); - Ok(path) - } - - /// Resolves the package nv from the provided specifier. - pub fn resolve_pkg_id_from_specifier( - &self, - specifier: &ModuleSpecifier, - ) -> Result<Option<NpmPackageId>, AnyError> { - let Some(cache_folder_id) = self - .fs_resolver - .resolve_package_cache_folder_id_from_specifier(specifier)? - else { - return Ok(None); - }; - Ok(Some( - self - .resolution - .resolve_pkg_id_from_pkg_cache_folder_id(&cache_folder_id)?, - )) - } - - /// Attempts to get the package size in bytes. - pub fn package_size( - &self, - package_id: &NpmPackageId, - ) -> Result<u64, AnyError> { - let package_folder = self.fs_resolver.package_folder(package_id)?; - Ok(crate::util::fs::dir_size(&package_folder)?) - } - - /// Adds package requirements to the resolver and ensures everything is setup. - pub async fn add_package_reqs( - &self, - packages: &[PackageReq], - ) -> Result<(), AnyError> { - if packages.is_empty() { - return Ok(()); - } - - self.resolution.add_package_reqs(packages).await?; - self.fs_resolver.cache_packages().await?; - - // If there's a lock file, update it with all discovered npm packages - if let Some(lockfile_mutex) = &self.maybe_lockfile { - let mut lockfile = lockfile_mutex.lock(); - self.lock(&mut lockfile)?; - } - - Ok(()) - } - - /// Sets package requirements to the resolver, removing old requirements and adding new ones. - /// - /// This will retrieve and resolve package information, but not cache any package files. - pub async fn set_package_reqs( - &self, - packages: &[PackageReq], - ) -> Result<(), AnyError> { - self.resolution.set_package_reqs(packages).await - } - - pub fn snapshot(&self) -> NpmResolutionSnapshot { - self.resolution.snapshot() - } - - pub fn lock(&self, lockfile: &mut Lockfile) -> Result<(), AnyError> { - self.resolution.lock(lockfile) - } - - pub async fn inject_synthetic_types_node_package( - &self, - ) -> Result<(), AnyError> { - // add and ensure this isn't added to the lockfile - let package_reqs = vec![PackageReq::from_str("@types/node").unwrap()]; - self.resolution.add_package_reqs(&package_reqs).await?; - self.fs_resolver.cache_packages().await?; - - Ok(()) - } - - pub async fn resolve_pending(&self) -> Result<(), AnyError> { - self.resolution.resolve_pending().await?; - self.fs_resolver.cache_packages().await?; - Ok(()) - } - - fn resolve_pkg_id_from_pkg_req( - &self, - req: &PackageReq, - ) -> Result<NpmPackageId, PackageReqNotFoundError> { - self.resolution.resolve_pkg_id_from_pkg_req(req) - } -} - -impl NpmResolver for ManagedCliNpmResolver { - fn resolve_package_folder_from_package( - &self, - name: &str, - referrer: &ModuleSpecifier, - mode: NodeResolutionMode, - ) -> Result<PathBuf, AnyError> { - let path = self - .fs_resolver - .resolve_package_folder_from_package(name, referrer, mode)?; - log::debug!("Resolved {} from {} to {}", name, referrer, path.display()); - Ok(path) - } - - fn resolve_package_folder_from_path( - &self, - specifier: &ModuleSpecifier, - ) -> Result<Option<PathBuf>, AnyError> { - self.resolve_pkg_folder_from_specifier(specifier) - } - - fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool { - let root_dir_url = self.fs_resolver.root_dir_url(); - debug_assert!(root_dir_url.as_str().ends_with('/')); - specifier.as_ref().starts_with(root_dir_url.as_str()) - } - - fn ensure_read_permission( - &self, - permissions: &dyn NodePermissions, - path: &Path, - ) -> Result<(), AnyError> { - self.fs_resolver.ensure_read_permission(permissions, path) - } -} - -impl CliNpmResolver for ManagedCliNpmResolver { - fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver> { - self - } - - fn root_dir_url(&self) -> &Url { - self.fs_resolver.root_dir_url() - } - - fn as_inner(&self) -> InnerCliNpmResolverRef { - InnerCliNpmResolverRef::Managed(self) - } - - fn node_modules_path(&self) -> Option<PathBuf> { - self.fs_resolver.node_modules_path() - } - - /// Checks if the provided package req's folder is cached. - fn is_pkg_req_folder_cached(&self, req: &PackageReq) -> bool { - self - .resolve_pkg_id_from_pkg_req(req) - .ok() - .and_then(|id| self.fs_resolver.package_folder(&id).ok()) - .map(|folder| folder.exists()) - .unwrap_or(false) - } - - fn resolve_pkg_nv_ref_from_pkg_req_ref( - &self, - req_ref: &NpmPackageReqReference, - ) -> Result<NpmPackageNvReference, PackageReqNotFoundError> { - let pkg_nv = self - .resolve_pkg_id_from_pkg_req(req_ref.req()) - .map(|id| id.nv)?; - Ok(NpmPackageNvReference::new(PackageNvReference { - nv: pkg_nv, - sub_path: req_ref.sub_path().map(|s| s.to_string()), - })) - } - - /// Resolve the root folder of the package the provided specifier is in. - /// - /// This will error when the provided specifier is not in an npm package. - fn resolve_pkg_folder_from_specifier( - &self, - specifier: &ModuleSpecifier, - ) -> Result<Option<PathBuf>, AnyError> { - let Some(path) = self - .fs_resolver - .resolve_package_folder_from_specifier(specifier)? - else { - return Ok(None); - }; - log::debug!( - "Resolved package folder of {} to {}", - specifier, - path.display() - ); - Ok(Some(path)) - } - - fn resolve_pkg_folder_from_deno_module_req( - &self, - req: &PackageReq, - ) -> Result<PathBuf, AnyError> { - let pkg_id = self.resolve_pkg_id_from_pkg_req(req)?; - self.resolve_pkg_folder_from_pkg_id(&pkg_id) - } - - fn resolve_pkg_folder_from_deno_module( - &self, - nv: &PackageNv, - ) -> Result<PathBuf, AnyError> { - let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(nv)?; - self.resolve_pkg_folder_from_pkg_id(&pkg_id) - } - - /// Gets the state of npm for the process. - fn get_npm_process_state(&self) -> String { - serde_json::to_string(&NpmProcessState { - snapshot: self - .resolution - .serialized_valid_snapshot() - .into_serialized(), - local_node_modules_path: self - .fs_resolver - .node_modules_path() - .map(|p| p.to_string_lossy().to_string()), - }) - .unwrap() - } - - fn package_reqs(&self) -> HashMap<PackageReq, PackageNv> { - self.resolution.package_reqs() - } -} - -pub fn create_npm_fs_resolver( - fs: Arc<dyn FileSystem>, - cache: Arc<NpmCache>, - progress_bar: &ProgressBar, - registry_url: Url, - resolution: Arc<NpmResolution>, - maybe_node_modules_path: Option<PathBuf>, - system_info: NpmSystemInfo, -) -> Arc<dyn NpmPackageFsResolver> { - match maybe_node_modules_path { - Some(node_modules_folder) => Arc::new(LocalNpmPackageResolver::new( - fs, - cache, - progress_bar.clone(), - registry_url, - node_modules_folder, - resolution, - system_info, - )), - None => Arc::new(GlobalNpmPackageResolver::new( - fs, - cache, - registry_url, - resolution, - system_info, - )), - } -} |