/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
cli/factory.rs
1 566 строк
53 KB
Bartek Iwańczuk
refactor(cli): replace single-method flag ext traits with free functions (#36491)
08 авг 2026, 02:53
Не верифицирован
08 авг 2026, 02:53
ce9bc92
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. use std::borrow::Cow; use std::future::Future; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; use deno_bundle_runtime::BundlePlatform; use deno_cache_dir::GlobalOrLocalHttpCache; use deno_cache_dir::npm::NpmCacheDir; use deno_config::workspace::WorkspaceDirectory; use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::futures::FutureExt; use deno_core::serde_json; use deno_core::url::Url; use deno_error::JsErrorBox; use deno_graph::packages::JsrVersionResolver; use deno_lib::args::CaData; use deno_lib::args::get_root_cert_store; use deno_lib::args::npm_process_state; use deno_lib::npm::NpmRegistryReadPermissionChecker; use deno_lib::npm::NpmRegistryReadPermissionCheckerMode; use deno_lib::npm::create_npm_process_state_provider; use deno_lib::worker::LibMainWorkerFactory; use deno_lib::worker::LibMainWorkerOptions; use deno_lib::worker::LibWorkerFactoryRoots; use deno_npm::resolution::NpmVersionResolver; use deno_npm_cache::NpmCacheSetting; use deno_npm_installer::NpmInstallerFactoryOptions; use deno_npm_installer::lifecycle_scripts::LifecycleScriptsExecutor; use deno_npm_installer::lifecycle_scripts::NullLifecycleScriptsExecutor; use deno_npm_installer::process_state::NpmProcessStateKind; use deno_npmrc::ResolvedNpmRc; use deno_resolver::cache::ParsedSourceCache; use deno_resolver::cjs::IsCjsResolutionMode; use deno_resolver::deno_json::CompilerOptionsOverrides; use deno_resolver::deno_json::CompilerOptionsResolver; use deno_resolver::factory::ConfigDiscoveryOption; use deno_resolver::factory::NpmProcessStateOptions; use deno_resolver::factory::ResolverFactoryOptions; use deno_resolver::factory::SpecifiedImportMapProvider; use deno_resolver::import_map::WorkspaceExternalImportMapLoader; use deno_resolver::loader::MemoryFiles; use deno_resolver::npm::DenoInNpmPackageChecker; use deno_resolver::workspace::WorkspaceResolver; use deno_runtime::CpuProfilerConfig; use deno_runtime::FeatureChecker; use deno_runtime::deno_fs; use deno_runtime::deno_fs::RealFs; use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_tls::RootCertStoreProvider; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_web::BlobStore; use deno_runtime::deno_web::BlobStoreTrait; use deno_runtime::permissions::RuntimePermissionDescriptorParser; use node_resolver::NodeConditionOptions; use node_resolver::NodeResolverOptions; use node_resolver::cache::NodeResolutionThreadLocalCache; use once_cell::sync::OnceCell; use crate::args::BundleFlags; use crate::args::CliLockfile; use crate::args::CliOptions; use crate::args::ConfigFlag; use crate::args::DenoSubcommand; use crate::args::Flags; use crate::args::FlagsExt; use crate::args::InstallFlags; use crate::args::InstallFlagsLocal; use crate::args::npm_system_info; use crate::cache::Caches; use crate::cache::CodeCache; use crate::cache::DenoDir; use crate::cache::GlobalHttpCache; use crate::cache::ModuleInfoCache; use crate::cache::SqliteNodeAnalysisCache; use crate::file_fetcher::CliFileFetcher; use crate::file_fetcher::CreateCliFileFetcherOptions; use crate::file_fetcher::TextDecodedFile; use crate::file_fetcher::create_cli_file_fetcher; use crate::graph_container::MainModuleGraphContainer; use crate::graph_util::FileWatcherReporter; use crate::graph_util::ModuleGraphBuilder; use crate::graph_util::ModuleGraphCreator; use crate::http_util::HttpClientProvider; use crate::module_loader::CliEmitter; use crate::module_loader::CliModuleLoaderFactory; use crate::module_loader::EszipModuleLoader; use crate::module_loader::ModuleLoadPreparer; use crate::node::CliNodeResolver; use crate::node::CliPackageJsonResolver; use crate::npm::CliNpmCache; use crate::npm::CliNpmCacheHttpClient; use crate::npm::CliNpmGraphResolver; use crate::npm::CliNpmInstaller; use crate::npm::CliNpmInstallerFactory; use crate::npm::CliNpmResolver; use crate::npm::DenoTaskLifeCycleScriptsExecutor; use crate::npm::NpmPackumentFormat; use crate::resolver::CliCjsTracker; use crate::resolver::CliNpmReqResolver; use crate::resolver::CliResolver; use crate::resolver::on_resolve_diagnostic; use crate::standalone::binary::DenoCompileBinaryWriter; use crate::sys::CliSys; use crate::tools::installer::BinNameResolver; use crate::tools::lint::LintRuleProvider; use crate::tools::run::hmr::HmrRunnerState; use crate::tsc::TypeCheckingCjsTracker; use crate::type_checker::TypeChecker; use crate::util::file_watcher::WatcherCommunicator; use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBarStyle; use crate::worker::CliMainWorkerFactory; use crate::worker::CliMainWorkerOptions; struct CliRootCertStoreProvider { cell: OnceCell<RootCertStore>, maybe_root_path: Option<PathBuf>, maybe_ca_stores: Option<Vec<String>>, maybe_ca_data: Option<CaData>, } impl CliRootCertStoreProvider { pub fn new( maybe_root_path: Option<PathBuf>, maybe_ca_stores: Option<Vec<String>>, maybe_ca_data: Option<CaData>, ) -> Self { Self { cell: Default::default(), maybe_root_path, maybe_ca_stores, maybe_ca_data, } } } impl RootCertStoreProvider for CliRootCertStoreProvider { fn get_or_try_init(&self) -> Result<&RootCertStore, JsErrorBox> { self .cell .get_or_try_init(|| { get_root_cert_store( &CliSys::default(), self.maybe_root_path.clone(), self.maybe_ca_stores.clone(), self.maybe_ca_data.clone(), ) }) .map_err(JsErrorBox::from_err) } } #[derive(Debug)] struct EszipModuleLoaderProvider { cli_options: Arc<CliOptions>, deferred: once_cell::sync::OnceCell<Arc<EszipModuleLoader>>, } impl EszipModuleLoaderProvider { pub async fn get(&self) -> Result<Option<&Arc<EszipModuleLoader>>, AnyError> { if self.cli_options.eszip() && let DenoSubcommand::Run(run_flags) = self.cli_options.sub_command() { if self.deferred.get().is_none() { let eszip_loader = EszipModuleLoader::create( &run_flags.script, self.cli_options.initial_cwd(), ) .await?; _ = self.deferred.set(Arc::new(eszip_loader)); } return Ok(Some(self.deferred.get().unwrap())); } Ok(None) } } #[derive(Debug)] struct CliSpecifiedImportMapProvider { cli_options: Arc<CliOptions>, file_fetcher: Arc<CliFileFetcher>, eszip_module_loader_provider: Arc<EszipModuleLoaderProvider>, workspace_external_import_map_loader: Arc<WorkspaceExternalImportMapLoader<CliSys>>, } #[async_trait::async_trait(?Send)] impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider { async fn get( &self, ) -> Result<Option<deno_resolver::workspace::SpecifiedImportMap>, AnyError> { async fn resolve_import_map_value_from_specifier( specifier: &Url, file_fetcher: &CliFileFetcher, ) -> Result<serde_json::Value, AnyError> { if specifier.scheme() == "data" { let data_url_text = deno_media_type::data_url::RawDataUrl::parse(specifier)?.decode()?; Ok(serde_json::from_str(&data_url_text)?) } else { let file = TextDecodedFile::decode( file_fetcher.fetch_bypass_permissions(specifier).await?, )?; Ok(serde_json::from_str(&file.source)?) } } let maybe_import_map_specifier = self.cli_options.resolve_specified_import_map_specifier()?; match maybe_import_map_specifier { Some(specifier) => { let value = match self.eszip_module_loader_provider.get().await? { Some(eszip) => eszip.load_import_map_value(&specifier)?, None => resolve_import_map_value_from_specifier( &specifier, &self.file_fetcher, ) .await .with_context(|| { format!("Unable to load '{}' import map", specifier) })?, }; Ok(Some(deno_resolver::workspace::SpecifiedImportMap { base_url: specifier, value, })) } None => { if let Some(import_map) = self.workspace_external_import_map_loader.get_or_load()? { let path_url = deno_path_util::url_from_file_path(&import_map.path)?; Ok(Some(deno_resolver::workspace::SpecifiedImportMap { base_url: path_url, value: import_map.value.clone(), })) } else { Ok(None) } } } } } pub type CliWorkspaceFactory = deno_resolver::factory::WorkspaceFactory<CliSys>; pub type CliResolverFactory = deno_resolver::factory::ResolverFactory<CliSys>; pub struct Deferred<T>(once_cell::unsync::OnceCell<T>); impl<T> Default for Deferred<T> { fn default() -> Self { Self(once_cell::unsync::OnceCell::default()) } } impl<T: std::fmt::Debug> std::fmt::Debug for Deferred<T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Deferred").field(&self.0).finish() } } impl<T> Deferred<T> { #[inline(always)] pub fn get_or_try_init( &self, create: impl FnOnce() -> Result<T, AnyError>, ) -> Result<&T, AnyError> { self.0.get_or_try_init(create) } #[inline(always)] pub fn get_or_init(&self, create: impl FnOnce() -> T) -> &T { self.0.get_or_init(create) } pub async fn get_or_try_init_async( &self, // some futures passed here are boxed because it was discovered // that they were called a lot, causing other futures to get // really big causing stack overflows on Windows create: impl Future<Output = Result<T, AnyError>>, ) -> Result<&T, AnyError> { if self.0.get().is_none() { // todo(dsherret): it would be more ideal if this enforced a // single executor and then we could make some initialization // concurrent let val = create.await?; _ = self.0.set(val); } Ok(self.0.get().unwrap()) } } #[derive(Default)] struct CliFactoryServices { blob_store: Deferred<Arc<dyn BlobStoreTrait>>, caches: Deferred<Arc<Caches>>, cli_options: Deferred<Arc<CliOptions>>, code_cache: Deferred<Arc<CodeCache>>, eszip_module_loader_provider: Deferred<Arc<EszipModuleLoaderProvider>>, feature_checker: Deferred<Arc<FeatureChecker>>, file_fetcher: Deferred<Arc<CliFileFetcher>>, fs: Deferred<Arc<dyn deno_fs::FileSystem>>, http_client_provider: Deferred<Arc<HttpClientProvider>>, main_graph_container: Deferred<Arc<MainModuleGraphContainer>>, graph_reporter: Deferred<Option<Arc<dyn deno_graph::source::Reporter>>>, memory_files: Arc<MemoryFiles>, module_graph_builder: Deferred<Arc<ModuleGraphBuilder>>, module_graph_creator: Deferred<Arc<ModuleGraphCreator>>, module_info_cache: Deferred<Arc<ModuleInfoCache>>, module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>, npm_installer_factory: Deferred<CliNpmInstallerFactory>, permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser<CliSys>>>, resolver_factory: Deferred<Arc<CliResolverFactory>>, root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>, root_permissions_container: Deferred<PermissionsContainer>, text_only_progress_bar: Deferred<ProgressBar>, type_checker: Deferred<Arc<TypeChecker>>, workspace_factory: Deferred<Arc<CliWorkspaceFactory>>, install_reporter: Deferred<Option<Arc<crate::tools::installer::InstallReporter>>>, } #[derive(Debug, Default)] struct CliFactoryOverrides { initial_cwd: Option<PathBuf>, workspace_directory: Option<Arc<WorkspaceDirectory>>, } pub struct CliFactory { watcher_communicator: Option<Arc<WatcherCommunicator>>, flags: Arc<Flags>, services: CliFactoryServices, overrides: CliFactoryOverrides, } impl CliFactory { pub fn from_flags(flags: Arc<Flags>) -> Self { Self { flags, watcher_communicator: None, services: Default::default(), overrides: Default::default(), } } pub fn from_flags_for_watcher( flags: Arc<Flags>, watcher_communicator: Arc<WatcherCommunicator>, ) -> Self { CliFactory { watcher_communicator: Some(watcher_communicator), flags, services: Default::default(), overrides: Default::default(), } } pub fn set_initial_cwd(&mut self, initial_cwd: PathBuf) { self.overrides.initial_cwd = Some(initial_cwd); } pub fn set_workspace_dir(&mut self, dir: Arc<WorkspaceDirectory>) { self.overrides.workspace_directory = Some(dir); } pub async fn maybe_lockfile( &self, ) -> Result<Option<&Arc<CliLockfile>>, AnyError> { self.npm_installer_factory()?.maybe_lockfile().await } pub fn cli_options(&self) -> Result<&Arc<CliOptions>, AnyError> { self.services.cli_options.get_or_try_init(|| { let workspace_factory = self.workspace_factory()?; let workspace_directory = workspace_factory.workspace_directory()?; CliOptions::from_flags( self.flags.clone(), workspace_factory.initial_cwd().clone(), workspace_directory.clone(), ) .map(Arc::new) }) } pub fn deno_dir(&self) -> Result<&DenoDir, AnyError> { Ok( self .workspace_factory()? .deno_dir_provider() .get_or_create()?, ) } pub fn caches(&self) -> Result<&Arc<Caches>, AnyError> { self.services.caches.get_or_try_init(|| { let cli_options = self.cli_options()?; let caches = Arc::new(Caches::new( self.workspace_factory()?.deno_dir_provider().clone(), )); // Warm up the caches we know we'll likely need based on the CLI mode match cli_options.sub_command() { DenoSubcommand::Run(_) | DenoSubcommand::Serve(_) | DenoSubcommand::Bench(_) | DenoSubcommand::Test(_) | DenoSubcommand::Check(_) => { _ = caches.dep_analysis_db(); _ = caches.node_analysis_db(); if cli_options.type_check_mode().is_true() { _ = caches.fast_check_db(); _ = caches.type_checking_cache_db(); } if cli_options.code_cache_enabled() { _ = caches.code_cache_db(); } } _ => {} } Ok(caches) }) } pub fn blob_store(&self) -> &Arc<dyn BlobStoreTrait> { self .services .blob_store .get_or_init(|| BlobStore::default_arc()) } pub fn bin_name_resolver(&self) -> Result<BinNameResolver<'_>, AnyError> { let http_client = self.http_client_provider(); let npm_api = self.npm_installer_factory()?.registry_info_provider()?; Ok(BinNameResolver::new( http_client, npm_api.as_ref(), self.npm_version_resolver()?, )) } pub fn root_cert_store_provider(&self) -> &Arc<dyn RootCertStoreProvider> { self.services.root_cert_store_provider.get_or_init(|| { Arc::new(CliRootCertStoreProvider::new( None, self.flags.ca_stores.clone(), self.flags.ca_data.clone(), )) }) } pub fn text_only_progress_bar(&self) -> &ProgressBar { self .services .text_only_progress_bar .get_or_init(|| ProgressBar::new(ProgressBarStyle::TextOnly)) } pub fn global_http_cache(&self) -> Result<&Arc<GlobalHttpCache>, AnyError> { Ok(self.workspace_factory()?.global_http_cache()?) } pub fn http_cache( &self, ) -> Result<&GlobalOrLocalHttpCache<CliSys>, AnyError> { Ok(self.workspace_factory()?.http_cache()?) } pub fn http_client_provider(&self) -> &Arc<HttpClientProvider> { self.services.http_client_provider.get_or_init(|| { Arc::new(HttpClientProvider::new( Some(self.root_cert_store_provider().clone()), self.flags.unsafely_ignore_certificate_errors.clone(), )) }) } fn eszip_module_loader_provider( &self, ) -> Result<&Arc<EszipModuleLoaderProvider>, AnyError> { self .services .eszip_module_loader_provider .get_or_try_init(|| { Ok(Arc::new(EszipModuleLoaderProvider { cli_options: self.cli_options()?.clone(), deferred: Default::default(), })) }) } pub fn file_fetcher(&self) -> Result<&Arc<CliFileFetcher>, AnyError> { self.services.file_fetcher.get_or_try_init(|| { let cli_options = self.cli_options()?; Ok(Arc::new(create_cli_file_fetcher( self.blob_store().clone(), self.http_cache()?.clone(), self.http_client_provider().clone(), self.services.memory_files.clone(), self.sys(), CreateCliFileFetcherOptions { allow_remote: !cli_options.no_remote(), cache_setting: cli_options.cache_setting(), download_log_level: log::Level::Info, progress_bar: Some(self.text_only_progress_bar().clone()), }, ))) }) } pub fn fs(&self) -> &Arc<dyn deno_fs::FileSystem> { self.services.fs.get_or_init(|| Arc::new(RealFs)) } pub fn memory_files(&self) -> &Arc<MemoryFiles> { &self.services.memory_files } pub fn sys(&self) -> CliSys { CliSys::default() // very cheap to make } pub fn in_npm_pkg_checker( &self, ) -> Result<&DenoInNpmPackageChecker, AnyError> { self.resolver_factory()?.in_npm_package_checker() } pub fn jsr_version_resolver( &self, ) -> Result<&Arc<JsrVersionResolver>, AnyError> { self.resolver_factory()?.jsr_version_resolver() } pub fn npm_cache(&self) -> Result<&Arc<CliNpmCache>, AnyError> { self.npm_installer_factory()?.npm_cache() } pub fn npm_cache_dir(&self) -> Result<&Arc<NpmCacheDir>, AnyError> { Ok(self.workspace_factory()?.npm_cache_dir()?) } pub fn npmrc(&self) -> Result<&Arc<ResolvedNpmRc>, AnyError> { Ok(self.workspace_factory()?.npmrc()?) } pub async fn npm_graph_resolver( &self, ) -> Result<&Arc<CliNpmGraphResolver>, AnyError> { self .npm_installer_factory()? .npm_deno_graph_resolver() .await } pub async fn npm_installer_if_managed( &self, ) -> Result<Option<&Arc<CliNpmInstaller>>, AnyError> { self .npm_installer_factory()? .npm_installer_if_managed() .await } pub fn npm_installer_factory( &self, ) -> Result<&CliNpmInstallerFactory, AnyError> { self.services.npm_installer_factory.get_or_try_init(|| { let cli_options = self.cli_options()?; let resolver_factory = self.resolver_factory()?; // the `no-downgrade` trust policy reads `_npmUser`/`attestations`, which // are only present in the full packument let needs_full_packument_for_trust = resolver_factory .workspace_factory() .npmrc() .ok() .map(|rc| rc.trust_policy != deno_npmrc::TrustPolicyConfig::Off) .unwrap_or(false); let needs_full_packument = needs_full_packument_for_trust || resolver_factory .minimum_dependency_age_config() .ok() .and_then(|c| c.age.as_ref().and_then(|d| d.into_option())) .is_some(); Ok(CliNpmInstallerFactory::new( resolver_factory.clone(), Arc::new(CliNpmCacheHttpClient::new( self.http_client_provider().clone(), self.text_only_progress_bar().clone(), if needs_full_packument { NpmPackumentFormat::Full } else { NpmPackumentFormat::Abbreviated }, )), match resolver_factory.npm_resolver()?.as_managed() { Some(managed_npm_resolver) => { Arc::new(DenoTaskLifeCycleScriptsExecutor::new( managed_npm_resolver.clone(), self.text_only_progress_bar().clone(), cli_options.npm_system_info(), )) as Arc<dyn LifecycleScriptsExecutor> } None => Arc::new(NullLifecycleScriptsExecutor), }, self.text_only_progress_bar().clone(), self .install_reporter()? .cloned() .map(|r| r as Arc<dyn deno_npm_installer::InstallReporter>), NpmInstallerFactoryOptions { clean_on_install: match cli_options.sub_command() { DenoSubcommand::Add { .. } | DenoSubcommand::ApproveScripts { .. } | DenoSubcommand::Remove { .. } | DenoSubcommand::Link { .. } | DenoSubcommand::Unlink { .. } | DenoSubcommand::Cache { .. } | DenoSubcommand::Ci { .. } | DenoSubcommand::Uninstall { .. } => true, DenoSubcommand::Install(flags) => match flags { InstallFlags::Local(flags, _) => match flags { InstallFlagsLocal::Add { .. } | InstallFlagsLocal::TopLevel { .. } => true, // someone might be terribly storing dependencies in a // module and needs to populate their node_modules directory // with the dependencies in that file InstallFlagsLocal::Entrypoints { .. } => false, }, InstallFlags::Global(_) => false, }, DenoSubcommand::Audit { .. } | DenoSubcommand::Bench { .. } | DenoSubcommand::Bundle { .. } | DenoSubcommand::Check { .. } | DenoSubcommand::Clean { .. } | DenoSubcommand::Compile { .. } | DenoSubcommand::Completions { .. } | DenoSubcommand::Desktop { .. } | DenoSubcommand::Coverage { .. } | DenoSubcommand::Deploy { .. } | DenoSubcommand::Doc { .. } | DenoSubcommand::Eval { .. } | DenoSubcommand::Fmt { .. } | DenoSubcommand::Init { .. } | DenoSubcommand::Info { .. } | DenoSubcommand::List { .. } | DenoSubcommand::JSONReference { .. } | DenoSubcommand::Jupyter { .. } | DenoSubcommand::Lsp | DenoSubcommand::SyncTypes { .. } | DenoSubcommand::Lint { .. } | DenoSubcommand::Repl { .. } | DenoSubcommand::Run { .. } | DenoSubcommand::Serve { .. } | DenoSubcommand::Task { .. } | DenoSubcommand::Test { .. } | DenoSubcommand::Transpile { .. } | DenoSubcommand::Outdated { .. } | DenoSubcommand::Types | DenoSubcommand::Upgrade { .. } | DenoSubcommand::Vendor | DenoSubcommand::Why { .. } | DenoSubcommand::Pack { .. } | DenoSubcommand::Publish { .. } | DenoSubcommand::Help { .. } | DenoSubcommand::X { .. } | DenoSubcommand::BumpVersion { .. } => false, }, // Always merge equivalent peer-dep variants when loading the // snapshot from a lockfile. This is an in-memory normalization // that collapses `NpmPackageId`s which differ only in // peer-dependency cycle-unrolling depth (the encoding changed // between releases, e.g. 2.7 -> 2.8). Without it, a complete // lockfile written by an older deno is treated as not satisfying // the requirements and the whole npm graph is re-resolved against // the registry, which fails under `--cached-only` (offline // isolates booting from an immutable, pre-baked `DENO_DIR`). See // denoland/deno#26427 for the original install-path dedup. This is // safe on `deno run`: the dedup only affects the in-memory // resolution snapshot and does not rewrite the user's lockfile // unless a real resolution runs (which the dedup is precisely what // avoids for an already-satisfied lockfile). dedup_lockfile_peer_variants: true, cache_setting: NpmCacheSetting::from_cache_setting( &cli_options.cache_setting(), ), caching_strategy: cli_options.default_npm_caching_strategy(), lifecycle_scripts_config: cli_options.lifecycle_scripts_config(), production: match cli_options.sub_command() { DenoSubcommand::Install(InstallFlags::Local(flags, _)) => { match flags { InstallFlagsLocal::TopLevel(f) => f.production, InstallFlagsLocal::Entrypoints(f) => f.production, InstallFlagsLocal::Add(_) => false, } } DenoSubcommand::Ci(f) => f.production, _ => false, }, skip_types: match cli_options.sub_command() { DenoSubcommand::Install(InstallFlags::Local(flags, _)) => { match flags { InstallFlagsLocal::TopLevel(f) => f.skip_types, InstallFlagsLocal::Entrypoints(f) => f.skip_types, InstallFlagsLocal::Add(_) => false, } } DenoSubcommand::Ci(f) => f.skip_types, _ => false, }, resolve_npm_resolution_snapshot: Box::new(|| { deno_lib::args::resolve_npm_resolution_snapshot(&CliSys::default()) }), }, )) }) } pub fn npm_version_resolver( &self, ) -> Result<&Arc<NpmVersionResolver>, AnyError> { self.resolver_factory()?.npm_version_resolver() } pub fn install_reporter( &self, ) -> Result<Option<&Arc<crate::tools::installer::InstallReporter>>, AnyError> { self .services .install_reporter .get_or_try_init(|| match self.cli_options()?.sub_command() { DenoSubcommand::Install(InstallFlags::Local(_, _)) | DenoSubcommand::Add(_) | DenoSubcommand::Cache(_) | DenoSubcommand::Ci(_) => Ok(Some(Arc::new( crate::tools::installer::InstallReporter::new(), ))), _ => Ok(None), }) .map(|opt| opt.as_ref()) } pub async fn npm_installer(&self) -> Result<&Arc<CliNpmInstaller>, AnyError> { self.npm_installer_factory()?.npm_installer().await } pub async fn npm_resolver(&self) -> Result<&CliNpmResolver, AnyError> { self.initialize_npm_resolution_if_managed().await?; self.resolver_factory()?.npm_resolver() } pub fn node_modules_dir_path(&self) -> Result<Option<&Path>, AnyError> { self.workspace_factory()?.node_modules_dir_path() } fn workspace_factory(&self) -> Result<&Arc<CliWorkspaceFactory>, AnyError> { self.services.workspace_factory.get_or_try_init(|| { let initial_cwd = match self.overrides.initial_cwd.clone() { Some(v) => v, // For modes that don't depend on a real cwd (REPL, eval), fall back // to a sentinel path when current_dir() fails — matches Node.js // semantics where `node --interactive` works even after the cwd has // been unlinked. None if matches!( self.flags.subcommand, DenoSubcommand::Repl(_) | DenoSubcommand::Eval(_) ) => { crate::util::env::resolve_cwd_or_fallback( self.flags.initial_cwd.as_deref(), ) } None => { crate::util::env::resolve_cwd(self.flags.initial_cwd.as_deref())? .into_owned() } }; let options = new_workspace_factory_options(&initial_cwd, &self.flags); let mut factory = CliWorkspaceFactory::new(self.sys(), initial_cwd, options); if let Some(workspace_dir) = &self.overrides.workspace_directory { factory.set_workspace_directory(workspace_dir.clone()); } Ok(Arc::new(factory)) }) } pub async fn workspace_resolver( &self, ) -> Result<&Arc<WorkspaceResolver<CliSys>>, AnyError> { self.initialize_npm_resolution_if_managed().await?; self.resolver_factory()?.workspace_resolver().await } pub async fn resolver(&self) -> Result<&Arc<CliResolver>, AnyError> { self.initialize_npm_resolution_if_managed().await?; self.resolver_factory()?.deno_resolver().await } pub fn graph_reporter( &self, ) -> Result<&Option<Arc<dyn deno_graph::source::Reporter>>, AnyError> { match self.cli_options()?.sub_command() { DenoSubcommand::Install(_) | DenoSubcommand::Ci(_) => { self.services.graph_reporter.get_or_try_init(|| { self.install_reporter().map(|opt| { opt.map(|r| r.clone() as Arc<dyn deno_graph::source::Reporter>) }) }) } _ => Ok(self.services.graph_reporter.get_or_init(|| { self .watcher_communicator .as_ref() .map(|i| FileWatcherReporter::new(i.clone())) .map(|i| Arc::new(i) as Arc<dyn deno_graph::source::Reporter>) })), } } pub fn module_info_cache(&self) -> Result<&Arc<ModuleInfoCache>, AnyError> { self.services.module_info_cache.get_or_try_init(|| { Ok(Arc::new(ModuleInfoCache::new( self.caches()?.dep_analysis_db(), self.resolver_factory()?.parsed_source_cache().clone(), ))) }) } pub fn code_cache(&self) -> Result<&Arc<CodeCache>, AnyError> { self.services.code_cache.get_or_try_init(|| { Ok(Arc::new(CodeCache::new(self.caches()?.code_cache_db()))) }) } pub fn parsed_source_cache( &self, ) -> Result<&Arc<ParsedSourceCache>, AnyError> { Ok(self.resolver_factory()?.parsed_source_cache()) } pub fn emitter(&self) -> Result<&Arc<CliEmitter>, AnyError> { self.resolver_factory()?.emitter() } pub async fn lint_rule_provider(&self) -> Result<LintRuleProvider, AnyError> { Ok(LintRuleProvider::new(Some( self.workspace_resolver().await?.clone(), ))) } pub async fn node_resolver(&self) -> Result<&Arc<CliNodeResolver>, AnyError> { self.initialize_npm_resolution_if_managed().await?; self.resolver_factory()?.node_resolver() } pub async fn npm_req_resolver( &self, ) -> Result<&Arc<CliNpmReqResolver>, AnyError> { self.initialize_npm_resolution_if_managed().await?; self.resolver_factory()?.npm_req_resolver() } async fn initialize_npm_resolution_if_managed(&self) -> Result<(), AnyError> { self .npm_installer_factory()? .initialize_npm_resolution_if_managed() .await } pub fn pkg_json_resolver( &self, ) -> Result<&Arc<CliPackageJsonResolver>, AnyError> { Ok(self.resolver_factory()?.pkg_json_resolver()) } pub fn compiler_options_resolver( &self, ) -> Result<&Arc<CompilerOptionsResolver>, AnyError> { self.resolver_factory()?.compiler_options_resolver() } pub async fn type_checker(&self) -> Result<&Arc<TypeChecker>, AnyError> { self .services .type_checker .get_or_try_init_async( async { let cli_options = self.cli_options()?; Ok(Arc::new(TypeChecker::new( self.caches()?.clone(), Arc::new(TypeCheckingCjsTracker::new( self.cjs_tracker()?.clone(), self.module_info_cache()?.clone(), )), cli_options.clone(), self.module_graph_builder().await?.clone(), self.node_resolver().await?.clone(), self.npm_resolver().await?.clone(), self.resolver_factory()?.pkg_json_resolver().clone(), self.sys(), self.compiler_options_resolver()?.clone(), if cli_options.code_cache_enabled() { Some(self.code_cache()?.clone()) } else { None }, ))) } .boxed_local(), ) .await } pub async fn module_graph_builder( &self, ) -> Result<&Arc<ModuleGraphBuilder>, AnyError> { self .services .module_graph_builder .get_or_try_init_async( async { let cli_options = self.cli_options()?; Ok(Arc::new(ModuleGraphBuilder::new( self.caches()?.clone(), self.cjs_tracker()?.clone(), cli_options.clone(), self.compiler_options_resolver()?.clone(), self.file_fetcher()?.clone(), self.global_http_cache()?.clone(), self.in_npm_pkg_checker()?.clone(), self.jsr_version_resolver()?.clone(), self.maybe_lockfile().await?.cloned(), self.graph_reporter()?.clone(), self.module_info_cache()?.clone(), self.npm_graph_resolver().await?.clone(), self.npm_installer_if_managed().await?.cloned(), self.npm_resolver().await?.clone(), self.resolver_factory()?.parsed_source_cache().clone(), self.text_only_progress_bar().clone(), self.resolver().await?.clone(), self.root_permissions_container()?.clone(), self.sys(), self.install_reporter()?.cloned().map(|r| { r as Arc<dyn deno_resolver::file_fetcher::GraphLoaderReporter> }), ))) } .boxed_local(), ) .await } pub async fn module_graph_creator( &self, ) -> Result<&Arc<ModuleGraphCreator>, AnyError> { self .services .module_graph_creator .get_or_try_init_async( async { let cli_options = self.cli_options()?; Ok(Arc::new(ModuleGraphCreator::new( cli_options.clone(), self.module_graph_builder().await?.clone(), self.type_checker().await?.clone(), ))) } .boxed_local(), ) .await } pub async fn main_module_graph_container( &self, ) -> Result<&Arc<MainModuleGraphContainer>, AnyError> { self .services .main_graph_container .get_or_try_init_async( async { Ok(Arc::new(MainModuleGraphContainer::new( self.cli_options()?.clone(), self.module_load_preparer().await?.clone(), self.root_permissions_container()?.clone(), ))) } .boxed_local(), ) .await } pub fn maybe_start_inspector_server(&self) -> Result<(), AnyError> { let cli_options = self.cli_options()?; if let Some((host, name, publish_uid)) = cli_options.resolve_inspector_server_options() { deno_runtime::deno_inspector_server::create_inspector_server( host, name, publish_uid, )?; } Ok(()) } pub async fn module_load_preparer( &self, ) -> Result<&Arc<ModuleLoadPreparer>, AnyError> { self .services .module_load_preparer .get_or_try_init_async( async { let cli_options = self.cli_options()?; Ok(Arc::new(ModuleLoadPreparer::new( cli_options.clone(), self.maybe_lockfile().await?.cloned(), self.module_graph_builder().await?.clone(), self.text_only_progress_bar().clone(), self.type_checker().await?.clone(), ))) } .boxed_local(), ) .await } pub fn cjs_tracker(&self) -> Result<&Arc<CliCjsTracker>, AnyError> { self.resolver_factory()?.cjs_tracker() } pub fn permission_desc_parser( &self, ) -> Result<&Arc<RuntimePermissionDescriptorParser<CliSys>>, AnyError> { self.services.permission_desc_parser.get_or_try_init(|| { Ok(Arc::new(RuntimePermissionDescriptorParser::new(self.sys()))) }) } pub fn feature_checker(&self) -> Result<&Arc<FeatureChecker>, AnyError> { self.services.feature_checker.get_or_try_init(|| { let cli_options = self.cli_options()?; let mut checker = FeatureChecker::default(); checker.set_exit_cb(Box::new(crate::unstable_exit_cb)); let unstable_features = cli_options.unstable_features(); for feature in deno_runtime::UNSTABLE_FEATURES { if unstable_features.contains(&feature.name) { checker.enable_feature(feature.name); } } // Deno Deploy: when DENO_KV_REQUIRES_DISTRIBUTED_DATABASE=error, force the // unstable KV feature on so `Deno.openKv()` is always exposed. The open // path then rejects with a clear "no database attached" error instead of // the runtime hiding the API and reporting "Deno.openKv is not a function". if std::env::var("DENO_KV_REQUIRES_DISTRIBUTED_DATABASE").as_deref() == Ok("error") && !checker.check("kv") { checker.enable_feature("kv"); } Ok(Arc::new(checker)) }) } pub async fn create_compile_binary_writer( &self, is_desktop: bool, ) -> Result<DenoCompileBinaryWriter<'_>, AnyError> { let cli_options = self.cli_options()?; Ok(DenoCompileBinaryWriter::new( self.resolver_factory()?.cjs_module_export_analyzer()?, self.cjs_tracker()?, self.cli_options()?, self.deno_dir()?, self.emitter()?, self.file_fetcher()?, self.http_client_provider(), self.npm_resolver().await?, self.workspace_resolver().await?.as_ref(), cli_options.npm_system_info(), is_desktop, )) } pub fn root_permissions_container( &self, ) -> Result<&PermissionsContainer, AnyError> { self .services .root_permissions_container .get_or_try_init(|| { let desc_parser = self.permission_desc_parser()?.clone(); let permissions = Permissions::from_options( desc_parser.as_ref(), &self.cli_options()?.permissions_options()?, )?; Ok(PermissionsContainer::new(desc_parser, permissions)) }) } fn workspace_external_import_map_loader( &self, ) -> Result<&Arc<WorkspaceExternalImportMapLoader<CliSys>>, AnyError> { Ok( self .workspace_factory()? .workspace_external_import_map_loader()?, ) } pub async fn create_cli_main_worker_factory( &self, ) -> Result<CliMainWorkerFactory, AnyError> { self .create_cli_main_worker_factory_with_roots(Default::default()) .await } pub async fn create_module_loader_factory( &self, ) -> Result<CliModuleLoaderFactory, AnyError> { let cli_options = self.cli_options()?; let cli_npm_resolver = self.npm_resolver().await?.clone(); let in_npm_pkg_checker = self.in_npm_pkg_checker()?; let workspace_factory = self.workspace_factory()?; let resolver_factory = self.resolver_factory()?; let npm_installer_factory = self.npm_installer_factory()?; let cjs_tracker = self.cjs_tracker()?.clone(); let npm_registry_permission_checker = { let mode = if resolver_factory.use_byonm()? { NpmRegistryReadPermissionCheckerMode::Byonm } else if let Some(node_modules_dir) = workspace_factory.node_modules_dir_path()? { NpmRegistryReadPermissionCheckerMode::Local( node_modules_dir.to_path_buf(), ) } else { NpmRegistryReadPermissionCheckerMode::Global( self.npm_cache_dir()?.root_dir().to_path_buf(), ) }; Arc::new(NpmRegistryReadPermissionChecker::new(self.sys(), mode)) }; let maybe_eszip_loader = self.eszip_module_loader_provider()?.get().await?.cloned(); let module_loader_factory = CliModuleLoaderFactory::new( cli_options, cjs_tracker, if cli_options.code_cache_enabled() { Some(self.code_cache()?.clone()) } else { None }, self.emitter()?.clone(), self.file_fetcher()?.clone(), npm_installer_factory .has_js_execution_started_flag() .clone(), in_npm_pkg_checker.clone(), self.main_module_graph_container().await?.clone(), self.memory_files().clone(), self.module_load_preparer().await?.clone(), npm_registry_permission_checker, cli_npm_resolver.clone(), resolver_factory.parsed_source_cache().clone(), resolver_factory.module_loader()?.clone(), self.resolver().await?.clone(), self.sys(), maybe_eszip_loader, self.watcher_communicator.clone(), ); Ok(module_loader_factory) } pub async fn create_cli_main_worker_factory_with_roots( &self, roots: LibWorkerFactoryRoots, ) -> Result<CliMainWorkerFactory, AnyError> { let cli_options = self.cli_options()?; let fs = self.fs(); let node_resolver = self.node_resolver().await?; let npm_resolver = self.npm_resolver().await?; // Provide the watcher communicator whenever running under the file watcher, // not just for HMR. `CliMainWorker::run()` uses its presence to detect that // it is under a watcher and route `Deno.exit()` through isolate termination // instead of `std::process::exit()`, which keeps `deno serve --watch` (which // goes through `run()` rather than `run_for_watcher`) alive across exits. // HMR-specific behaviour is gated separately on `create_hmr_runner`. See // issue #7590. let maybe_file_watcher_communicator = self.watcher_communicator.clone(); let pkg_json_resolver = self.pkg_json_resolver()?; let module_loader_factory = self.create_module_loader_factory().await?; self.maybe_start_inspector_server()?; let maybe_cpu_prof_config_for_workers = cli_options.cpu_prof_dir().map(|dir| CpuProfilerConfig { dir, name: cli_options.cpu_prof_name(), interval: cli_options.cpu_prof_interval(), md: cli_options.cpu_prof_md(), flamegraph: cli_options.cpu_prof_flamegraph(), }); let lib_main_worker_factory = LibMainWorkerFactory::new( self.blob_store().clone(), if cli_options.code_cache_enabled() { Some(self.code_cache()?.clone()) } else { None }, None, // DenoRtNativeAddonLoader self.feature_checker()?.clone(), fs.clone(), cli_options.coverage_dir(), maybe_cpu_prof_config_for_workers, Box::new(module_loader_factory), node_resolver.clone(), create_npm_process_state_provider(npm_resolver), pkg_json_resolver.clone(), self.root_cert_store_provider().clone(), cli_options.resolve_storage_key_resolver(), self.sys(), self.create_lib_main_worker_options()?, roots, Some(Arc::new(crate::tools::bundle::CliBundleProvider::new( self.flags.clone(), ))), ); Ok(CliMainWorkerFactory::new( lib_main_worker_factory, maybe_file_watcher_communicator, self.maybe_lockfile().await?.cloned(), self.npm_installer_if_managed().await?.cloned(), npm_resolver.clone(), self.text_only_progress_bar().clone(), self.create_cli_main_worker_options()?, self.root_permissions_container()?.clone(), )) } pub fn create_lib_main_worker_options( &self, ) -> Result<LibMainWorkerOptions, AnyError> { let cli_options = self.cli_options()?; let workspace_factory = self.workspace_factory()?; Ok(LibMainWorkerOptions { argv: cli_options.argv().clone(), // This optimization is only available for "run" subcommand // because we need to register new ops for testing and jupyter // integration. skip_op_registration: cli_options.sub_command().is_run(), log_level: cli_options.log_level().unwrap_or(log::Level::Info).into(), enable_testing_features: cli_options.enable_testing_features(), has_node_modules_dir: workspace_factory .node_modules_dir_path()? .is_some(), inspect_brk: cli_options.inspect_brk(), inspect_wait: cli_options.inspect_wait(), trace_ops: cli_options.trace_ops().clone(), is_standalone: false, auto_serve: std::env::var("DENO_AUTO_SERVE").is_ok(), is_inspecting: cli_options.is_inspecting(), location: cli_options.location_flag().clone(), // if the user ran a binary command, we'll need to set process.argv[0] // to be the name of the binary command instead of deno argv0: cli_options .take_binary_npm_command_name() .or(std::env::args().next()), node_debug: std::env::var("NODE_DEBUG").ok(), node_cluster_unique_id: std::env::var("NODE_UNIQUE_ID").ok(), node_cluster_sched_policy: std::env::var("NODE_CLUSTER_SCHED_POLICY") .ok(), origin_data_folder_path: Some(self.deno_dir()?.origin_data_folder_path()), seed: cli_options.seed(), unsafely_ignore_certificate_errors: cli_options .unsafely_ignore_certificate_errors() .clone(), node_ipc_init: cli_options.node_ipc_init(&self.sys())?, serve_port: cli_options.serve_port(), serve_host: cli_options.serve_host(), otel_config: cli_options.otel_config(), no_legacy_abort: cli_options.no_legacy_abort(), startup_snapshot: deno_snapshots::CLI_SNAPSHOT, residual_lazy_js_sources: deno_snapshots::RESIDUAL_LAZY_JS, residual_lazy_esm_sources: deno_snapshots::RESIDUAL_LAZY_ESM, enable_raw_imports: cli_options.unstable_raw_imports(), close_on_idle: true, maybe_initial_cwd: Some(deno_path_util::url_from_directory_path( cli_options.initial_cwd(), )?), // Deno 2.8 exposes an `OffscreenCanvas` global whose 2D context is // unimplemented (`getContext("2d")` returns null). Libraries that // feature-detect on the global's presence then crash. Setting this // removes the global, restoring the pre-2.8 fallback path. Truthy // values are `1` and `true`. disable_offscreen_canvas: matches!( std::env::var("DENO_DISABLE_OFFSCREEN_CANVAS").as_deref(), Ok("1") | Ok("true") ), }) } fn create_cli_main_worker_options( &self, ) -> Result<CliMainWorkerOptions, AnyError> { let cli_options = self.cli_options()?; let create_hmr_runner = if cli_options.has_hmr() { let watcher_communicator = self.watcher_communicator.clone().unwrap(); let emitter = self.emitter()?.clone(); let fn_: crate::worker::CreateHmrRunnerCb = Box::new(move || { HmrRunnerState::new(emitter.clone(), watcher_communicator.clone()) }); Some(fn_) } else { None }; let maybe_coverage_dir = cli_options.coverage_dir(); let maybe_cpu_prof_config = cli_options.cpu_prof_dir().map(|dir| CpuProfilerConfig { dir, name: cli_options.cpu_prof_name(), interval: cli_options.cpu_prof_interval(), md: cli_options.cpu_prof_md(), flamegraph: cli_options.cpu_prof_flamegraph(), }); let initial_cwd = deno_path_util::url_from_directory_path(cli_options.initial_cwd())?; Ok(CliMainWorkerOptions { needs_test_modules: cli_options.sub_command().needs_test(), create_hmr_runner, maybe_coverage_dir, maybe_cpu_prof_config, default_npm_caching_strategy: cli_options.default_npm_caching_strategy(), initial_cwd: Arc::new(initial_cwd), }) } pub fn resolver_factory(&self) -> Result<&Arc<CliResolverFactory>, AnyError> { self.services.resolver_factory.get_or_try_init(|| { let options = self.cli_options()?; let caches = self.caches()?; let node_analysis_cache = Arc::new(SqliteNodeAnalysisCache::new(caches.node_analysis_db())); Ok(Arc::new(CliResolverFactory::new( self.workspace_factory()?.clone(), ResolverFactoryOptions { compiler_options_overrides: CompilerOptionsOverrides { no_transpile: false, force_check_js: matches!( &self.flags.subcommand, DenoSubcommand::Check(check_flags) if check_flags.check_js ), source_map_base: None, preserve_jsx: false, // Untyped execution environments (e.g. isolates running with // --no-check) can opt out of verbatimModuleSyntax, which // otherwise leaves dangling type-only re-exports that crash at // runtime. Truthy values are `1` and `true`. force_disable_verbatim_module_syntax: matches!( std::env::var("DENO_DISABLE_VERBATIM_MODULE_SYNTAX").as_deref(), Ok("1") | Ok("true") ), }, is_cjs_resolution_mode: if options.is_node_main() || options.unstable_detect_cjs() { IsCjsResolutionMode::ImplicitTypeCommonJs } else if options.detect_cjs() { IsCjsResolutionMode::ExplicitTypeCommonJs } else { IsCjsResolutionMode::Disabled }, newest_dependency_date: self.flags.minimum_dependency_age, node_analysis_cache: Some(node_analysis_cache), node_resolver_options: NodeResolverOptions { conditions: NodeConditionOptions { conditions: options .node_conditions() .iter() .map(|c| Cow::Owned(c.clone())) .collect(), import_conditions_override: None, require_conditions_override: None, }, typescript_version: Some( deno_semver::Version::parse_standard( deno_lib::version::DENO_VERSION_INFO.typescript, ) .unwrap(), ), bundle_mode: matches!( self.flags.subcommand, DenoSubcommand::Bundle(_) ) || self.flags.internal.force_bundle_mode, is_browser_platform: matches!( self.flags.subcommand, DenoSubcommand::Bundle(BundleFlags { platform: BundlePlatform::Browser, .. }) ), }, node_code_translator_mode: if matches!( options.sub_command(), DenoSubcommand::Bundle(_) ) || self .flags .internal .force_bundle_mode { node_resolver::analyze::NodeCodeTranslatorMode::Disabled } else { node_resolver::analyze::NodeCodeTranslatorMode::ModuleLoader }, node_resolution_cache: Some(Arc::new(NodeResolutionThreadLocalCache)), npm_system_info: npm_system_info(&self.flags.subcommand), specified_import_map: Some(Box::new(CliSpecifiedImportMapProvider { cli_options: options.clone(), eszip_module_loader_provider: self .eszip_module_loader_provider()? .clone(), file_fetcher: self.file_fetcher()?.clone(), workspace_external_import_map_loader: self .workspace_external_import_map_loader()? .clone(), })), unstable_sloppy_imports: options.unstable_sloppy_imports(), on_mapped_resolution_diagnostic: Some(Arc::new( on_resolve_diagnostic, )), package_json_cache: Some(Arc::new( node_resolver::PackageJsonThreadLocalCache, )), package_json_dep_resolution: match &self.flags.subcommand { DenoSubcommand::Publish(_) => { // the node_modules directory is not published to jsr, so resolve // dependencies via the package.json rather than using node resolution Some(deno_resolver::workspace::PackageJsonDepResolution::Enabled) } _ => None, }, allow_json_imports: if matches!( self.flags.subcommand, DenoSubcommand::Bundle(_) ) || self.flags.internal.force_bundle_mode { deno_resolver::loader::AllowJsonImports::Always } else { deno_resolver::loader::AllowJsonImports::WithAttribute }, require_modules: options.require_modules()?, }, ))) }) } } fn new_workspace_factory_options( initial_cwd: &Path, flags: &Flags, ) -> deno_resolver::factory::WorkspaceFactoryOptions { deno_resolver::factory::WorkspaceFactoryOptions { additional_config_file_names: if matches!( flags.subcommand, DenoSubcommand::Publish(..) ) { &["jsr.json", "jsr.jsonc"] } else { &[] }, config_discovery: match &flags.config_flag { ConfigFlag::Discover => { if let Some(start_paths) = flags.config_path_args(initial_cwd) { ConfigDiscoveryOption::Discover { start_paths } } else { ConfigDiscoveryOption::Disabled } } ConfigFlag::Path(path) => { ConfigDiscoveryOption::Path(initial_cwd.join(path)) } ConfigFlag::Disabled => ConfigDiscoveryOption::Disabled, }, maybe_custom_deno_dir_root: flags.internal.cache_path.clone(), // For `deno install/add/remove/init` we want to force the managed // resolver so it can set up the `node_modules/` directory. is_package_manager_subcommand: matches!( flags.subcommand, DenoSubcommand::Add(_) | DenoSubcommand::Audit(_) | DenoSubcommand::Ci(_) | DenoSubcommand::Clean(_) | DenoSubcommand::Init(_) | DenoSubcommand::Install(_) | DenoSubcommand::Link(_) | DenoSubcommand::List(_) | DenoSubcommand::Outdated(_) | DenoSubcommand::Remove(_) | DenoSubcommand::Unlink(_) | DenoSubcommand::Uninstall(_) | DenoSubcommand::ApproveScripts(_) ), no_lock: flags.no_lock || matches!( flags.subcommand, DenoSubcommand::Install(InstallFlags::Global(..)) | DenoSubcommand::Uninstall(_) ), // Seed deno.lock from package-lock.json only when the user is explicitly // setting up dependencies via `deno install` (local form). import_npm_lockfile: matches!( flags.subcommand, DenoSubcommand::Install(InstallFlags::Local(..)) ), frozen_lockfile: flags.frozen_lockfile, lock_arg: flags.lock.as_ref().map(|l| initial_cwd.join(l)), lockfile_skip_write: flags.internal.lockfile_skip_write, no_npm: flags.no_npm, node_modules_dir: flags.node_modules_dir, node_modules_linker: flags.node_modules_linker, npm_process_state: npm_process_state(&CliSys::default()).as_ref().map( |s| { use deno_npm_installer::process_state::NpmProcessStateLinkerMode; NpmProcessStateOptions { node_modules_dir: s .local_node_modules_path .as_ref() .map(|s| Cow::Borrowed(s.as_str())), is_byonm: matches!(s.kind, NpmProcessStateKind::Byonm), linker_mode: Some(match s.linker_mode { NpmProcessStateLinkerMode::Isolated => { deno_config::deno_json::NodeModulesLinkerMode::Isolated } NpmProcessStateLinkerMode::Hoisted => { deno_config::deno_json::NodeModulesLinkerMode::Hoisted } }), } }, ), root_node_modules_dir_override: flags .internal .root_node_modules_dir_override .clone(), vendor: flags.vendor, } }