Skip to content

Commit

Permalink
refactor: create NpmInstaller (denoland#27626)
Browse files Browse the repository at this point in the history
This separates npm resolution code from npm installation (more work
towards moving resolution code out of the CLI and cleaning up this
code).
  • Loading branch information
dsherret authored Jan 13, 2025
1 parent 5a39f2f commit 9dbb99a
Show file tree
Hide file tree
Showing 39 changed files with 1,367 additions and 1,141 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ deno_bench_util = { version = "0.179.0", path = "./bench_util" }
deno_config = { version = "=0.43.0", features = ["workspace", "sync"] }
deno_lockfile = "=0.24.0"
deno_media_type = { version = "0.2.3", features = ["module_specifier"] }
deno_npm = "=0.27.0"
deno_npm = "=0.27.2"
deno_path_util = "=0.3.0"
deno_permissions = { version = "0.44.0", path = "./runtime/permissions" }
deno_runtime = { version = "0.193.0", path = "./runtime" }
Expand Down
223 changes: 180 additions & 43 deletions cli/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ use deno_core::error::AnyError;
use deno_core::futures::FutureExt;
use deno_core::FeatureChecker;
use deno_error::JsErrorBox;
use deno_npm_cache::NpmCacheSetting;
use deno_resolver::cjs::IsCjsResolutionMode;
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
use deno_resolver::npm::managed::NpmResolutionCell;
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
use deno_resolver::npm::NpmReqResolverOptions;
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
Expand Down Expand Up @@ -67,19 +69,27 @@ use crate::node::CliNodeCodeTranslator;
use crate::node::CliNodeResolver;
use crate::node::CliPackageJsonResolver;
use crate::npm::create_cli_npm_resolver;
use crate::npm::installer::NpmInstaller;
use crate::npm::installer::NpmResolutionInstaller;
use crate::npm::CliByonmNpmResolverCreateOptions;
use crate::npm::CliManagedNpmResolverCreateOptions;
use crate::npm::CliNpmCache;
use crate::npm::CliNpmCacheHttpClient;
use crate::npm::CliNpmRegistryInfoProvider;
use crate::npm::CliNpmResolver;
use crate::npm::CliNpmResolverCreateOptions;
use crate::npm::CliNpmResolverManagedSnapshotOption;
use crate::npm::CliNpmTarballCache;
use crate::npm::NpmRegistryReadPermissionChecker;
use crate::npm::NpmRegistryReadPermissionCheckerMode;
use crate::npm::NpmResolutionInitializer;
use crate::resolver::CjsTracker;
use crate::resolver::CliDenoResolver;
use crate::resolver::CliNpmGraphResolver;
use crate::resolver::CliNpmReqResolver;
use crate::resolver::CliResolver;
use crate::resolver::CliResolverOptions;
use crate::resolver::CliSloppyImportsResolver;
use crate::resolver::FoundPackageJsonDepFlag;
use crate::resolver::NpmModuleLoader;
use crate::standalone::binary::DenoCompileBinaryWriter;
use crate::sys::CliSys;
Expand Down Expand Up @@ -188,6 +198,7 @@ struct CliFactoryServices {
emitter: Deferred<Arc<Emitter>>,
feature_checker: Deferred<Arc<FeatureChecker>>,
file_fetcher: Deferred<Arc<CliFileFetcher>>,
found_pkg_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
global_http_cache: Deferred<Arc<GlobalHttpCache>>,
http_cache: Deferred<Arc<dyn HttpCache>>,
Expand All @@ -202,9 +213,18 @@ struct CliFactoryServices {
module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
node_resolver: Deferred<Arc<CliNodeResolver>>,
npm_cache: Deferred<Arc<CliNpmCache>>,
npm_cache_dir: Deferred<Arc<NpmCacheDir>>,
npm_cache_http_client: Deferred<Arc<CliNpmCacheHttpClient>>,
npm_graph_resolver: Deferred<Arc<CliNpmGraphResolver>>,
npm_installer: Deferred<Arc<NpmInstaller>>,
npm_registry_info_provider: Deferred<Arc<CliNpmRegistryInfoProvider>>,
npm_req_resolver: Deferred<Arc<CliNpmReqResolver>>,
npm_resolution: Arc<NpmResolutionCell>,
npm_resolution_initializer: Deferred<Arc<NpmResolutionInitializer>>,
npm_resolution_installer: Deferred<Arc<NpmResolutionInstaller>>,
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>,
npm_tarball_cache: Deferred<Arc<CliNpmTarballCache>>,
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
permission_desc_parser:
Deferred<Arc<RuntimePermissionDescriptorParser<CliSys>>>,
Expand Down Expand Up @@ -398,6 +418,18 @@ impl CliFactory {
})
}

pub fn npm_cache(&self) -> Result<&Arc<CliNpmCache>, AnyError> {
self.services.npm_cache.get_or_try_init(|| {
let cli_options = self.cli_options()?;
Ok(Arc::new(CliNpmCache::new(
self.npm_cache_dir()?.clone(),
self.sys(),
NpmCacheSetting::from_cache_setting(&cli_options.cache_setting()),
cli_options.npmrc().clone(),
)))
})
}

pub fn npm_cache_dir(&self) -> Result<&Arc<NpmCacheDir>, AnyError> {
self.services.npm_cache_dir.get_or_try_init(|| {
let global_path = self.deno_dir()?.npm_folder_path();
Expand All @@ -410,6 +442,123 @@ impl CliFactory {
})
}

pub fn npm_cache_http_client(&self) -> &Arc<CliNpmCacheHttpClient> {
self.services.npm_cache_http_client.get_or_init(|| {
Arc::new(CliNpmCacheHttpClient::new(
self.http_client_provider().clone(),
self.text_only_progress_bar().clone(),
))
})
}

pub fn npm_graph_resolver(
&self,
) -> Result<&Arc<CliNpmGraphResolver>, AnyError> {
self.services.npm_graph_resolver.get_or_try_init(|| {
let cli_options = self.cli_options()?;
Ok(Arc::new(CliNpmGraphResolver::new(
self.npm_installer_if_managed()?.cloned(),
self.services.found_pkg_json_dep_flag.clone(),
cli_options.unstable_bare_node_builtins(),
cli_options.default_npm_caching_strategy(),
)))
})
}

pub fn npm_installer_if_managed(
&self,
) -> Result<Option<&Arc<NpmInstaller>>, AnyError> {
let options = self.cli_options()?;
if options.use_byonm() || options.no_npm() {
Ok(None)
} else {
Ok(Some(self.npm_installer()?))
}
}

pub fn npm_installer(&self) -> Result<&Arc<NpmInstaller>, AnyError> {
self.services.npm_installer.get_or_try_init(|| {
let cli_options = self.cli_options()?;
Ok(Arc::new(NpmInstaller::new(
self.npm_cache()?.clone(),
Arc::new(NpmInstallDepsProvider::from_workspace(
cli_options.workspace(),
)),
self.npm_resolution().clone(),
self.npm_resolution_initializer()?.clone(),
self.npm_resolution_installer()?.clone(),
self.text_only_progress_bar(),
self.sys(),
self.npm_tarball_cache()?.clone(),
cli_options.maybe_lockfile().cloned(),
cli_options.node_modules_dir_path().cloned(),
cli_options.lifecycle_scripts_config(),
cli_options.npm_system_info(),
)))
})
}

pub fn npm_registry_info_provider(
&self,
) -> Result<&Arc<CliNpmRegistryInfoProvider>, AnyError> {
self
.services
.npm_registry_info_provider
.get_or_try_init(|| {
let cli_options = self.cli_options()?;
Ok(Arc::new(CliNpmRegistryInfoProvider::new(
self.npm_cache()?.clone(),
self.npm_cache_http_client().clone(),
cli_options.npmrc().clone(),
)))
})
}

pub fn npm_resolution(&self) -> &Arc<NpmResolutionCell> {
&self.services.npm_resolution
}

pub fn npm_resolution_initializer(
&self,
) -> Result<&Arc<NpmResolutionInitializer>, AnyError> {
self
.services
.npm_resolution_initializer
.get_or_try_init(|| {
let cli_options = self.cli_options()?;
Ok(Arc::new(NpmResolutionInitializer::new(
self.npm_registry_info_provider()?.clone(),
self.npm_resolution().clone(),
match cli_options.resolve_npm_resolution_snapshot()? {
Some(snapshot) => {
CliNpmResolverManagedSnapshotOption::Specified(Some(snapshot))
}
None => match cli_options.maybe_lockfile() {
Some(lockfile) => {
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
lockfile.clone(),
)
}
None => CliNpmResolverManagedSnapshotOption::Specified(None),
},
},
)))
})
}

pub fn npm_resolution_installer(
&self,
) -> Result<&Arc<NpmResolutionInstaller>, AnyError> {
self.services.npm_resolution_installer.get_or_try_init(|| {
let cli_options = self.cli_options()?;
Ok(Arc::new(NpmResolutionInstaller::new(
self.npm_registry_info_provider()?.clone(),
self.npm_resolution().clone(),
cli_options.maybe_lockfile().cloned(),
)))
})
}

pub async fn npm_resolver(
&self,
) -> Result<&Arc<dyn CliNpmResolver>, AnyError> {
Expand All @@ -419,7 +568,7 @@ impl CliFactory {
.get_or_try_init_async(
async {
let cli_options = self.cli_options()?;
create_cli_npm_resolver(if cli_options.use_byonm() {
Ok(create_cli_npm_resolver(if cli_options.use_byonm() {
CliNpmResolverCreateOptions::Byonm(
CliByonmNpmResolverCreateOptions {
sys: self.sys(),
Expand All @@ -438,52 +587,43 @@ impl CliFactory {
},
)
} else {
self
.npm_resolution_initializer()?
.ensure_initialized()
.await?;
CliNpmResolverCreateOptions::Managed(
CliManagedNpmResolverCreateOptions {
http_client_provider: self.http_client_provider().clone(),
npm_install_deps_provider: Arc::new(
NpmInstallDepsProvider::from_workspace(
cli_options.workspace(),
),
),
sys: self.sys(),
snapshot: match cli_options.resolve_npm_resolution_snapshot()? {
Some(snapshot) => {
CliNpmResolverManagedSnapshotOption::Specified(Some(
snapshot,
))
}
None => match cli_options.maybe_lockfile() {
Some(lockfile) => {
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
lockfile.clone(),
)
}
None => {
CliNpmResolverManagedSnapshotOption::Specified(None)
}
},
},
maybe_lockfile: cli_options.maybe_lockfile().cloned(),
npm_resolution: self.npm_resolution().clone(),
npm_cache_dir: self.npm_cache_dir()?.clone(),
cache_setting: cli_options.cache_setting(),
text_only_progress_bar: self.text_only_progress_bar().clone(),
maybe_node_modules_path: cli_options
.node_modules_dir_path()
.cloned(),
npm_system_info: cli_options.npm_system_info(),
npmrc: cli_options.npmrc().clone(),
lifecycle_scripts: cli_options.lifecycle_scripts_config(),
},
)
})
.await
}))
}
.boxed_local(),
)
.await
}

pub fn npm_tarball_cache(
&self,
) -> Result<&Arc<CliNpmTarballCache>, AnyError> {
self.services.npm_tarball_cache.get_or_try_init(|| {
let cli_options = self.cli_options()?;
Ok(Arc::new(CliNpmTarballCache::new(
self.npm_cache()?.clone(),
self.npm_cache_http_client().clone(),
self.sys(),
cli_options.npmrc().clone(),
)))
})
}

pub fn sloppy_imports_resolver(
&self,
) -> Result<Option<&Arc<CliSloppyImportsResolver>>, AnyError> {
Expand Down Expand Up @@ -571,17 +711,10 @@ impl CliFactory {
.resolver
.get_or_try_init_async(
async {
let cli_options = self.cli_options()?;
Ok(Arc::new(CliResolver::new(CliResolverOptions {
npm_resolver: if cli_options.no_npm() {
None
} else {
Some(self.npm_resolver().await?.clone())
},
bare_node_builtins_enabled: cli_options
.unstable_bare_node_builtins(),
deno_resolver: self.deno_resolver().await?.clone(),
})))
Ok(Arc::new(CliResolver::new(
self.deno_resolver().await?.clone(),
self.services.found_pkg_json_dep_flag.clone(),
)))
}
.boxed_local(),
)
Expand Down Expand Up @@ -752,6 +885,7 @@ impl CliFactory {
cli_options.clone(),
self.module_graph_builder().await?.clone(),
self.node_resolver().await?.clone(),
self.npm_installer_if_managed()?.cloned(),
self.npm_resolver().await?.clone(),
self.sys(),
)))
Expand All @@ -777,6 +911,8 @@ impl CliFactory {
cli_options.maybe_lockfile().cloned(),
self.maybe_file_watcher_reporter().clone(),
self.module_info_cache()?.clone(),
self.npm_graph_resolver()?.clone(),
self.npm_installer_if_managed()?.cloned(),
self.npm_resolver().await?.clone(),
self.parsed_source_cache().clone(),
self.resolver().await?.clone(),
Expand All @@ -797,7 +933,7 @@ impl CliFactory {
let cli_options = self.cli_options()?;
Ok(Arc::new(ModuleGraphCreator::new(
cli_options.clone(),
self.npm_resolver().await?.clone(),
self.npm_installer_if_managed()?.cloned(),
self.module_graph_builder().await?.clone(),
self.type_checker().await?.clone(),
)))
Expand Down Expand Up @@ -997,6 +1133,7 @@ impl CliFactory {
self.sys(),
)),
node_resolver.clone(),
self.npm_installer_if_managed()?.cloned(),
npm_resolver.clone(),
pkg_json_resolver,
self.root_cert_store_provider().clone(),
Expand Down
Loading

0 comments on commit 9dbb99a

Please sign in to comment.