mirror of
https://github.com/denoland/deno.git
synced 2025-01-19 12:16:17 -05:00
refactor: create NpmInstaller
(#27626)
This separates npm resolution code from npm installation (more work towards moving resolution code out of the CLI and cleaning up this code).
This commit is contained in:
parent
5a39f2f096
commit
9dbb99a83c
39 changed files with 1367 additions and 1141 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -2074,9 +2074,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_npm"
|
name = "deno_npm"
|
||||||
version = "0.27.0"
|
version = "0.27.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f818ad5dc4c206b50b5cfa6f10b4b94b127e15c8342c152768eba40c225ca23"
|
checksum = "4adceb4c34f10e837d0e3ae76e88dddefb13e83c05c1ef1699fa5519241c9d27"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"capacity_builder 0.5.0",
|
"capacity_builder 0.5.0",
|
||||||
|
|
|
@ -54,7 +54,7 @@ deno_bench_util = { version = "0.179.0", path = "./bench_util" }
|
||||||
deno_config = { version = "=0.43.0", features = ["workspace", "sync"] }
|
deno_config = { version = "=0.43.0", features = ["workspace", "sync"] }
|
||||||
deno_lockfile = "=0.24.0"
|
deno_lockfile = "=0.24.0"
|
||||||
deno_media_type = { version = "0.2.3", features = ["module_specifier"] }
|
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_path_util = "=0.3.0"
|
||||||
deno_permissions = { version = "0.44.0", path = "./runtime/permissions" }
|
deno_permissions = { version = "0.44.0", path = "./runtime/permissions" }
|
||||||
deno_runtime = { version = "0.193.0", path = "./runtime" }
|
deno_runtime = { version = "0.193.0", path = "./runtime" }
|
||||||
|
|
223
cli/factory.rs
223
cli/factory.rs
|
@ -11,8 +11,10 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::FeatureChecker;
|
use deno_core::FeatureChecker;
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
|
use deno_npm_cache::NpmCacheSetting;
|
||||||
use deno_resolver::cjs::IsCjsResolutionMode;
|
use deno_resolver::cjs::IsCjsResolutionMode;
|
||||||
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
|
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
|
||||||
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
||||||
use deno_resolver::npm::NpmReqResolverOptions;
|
use deno_resolver::npm::NpmReqResolverOptions;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||||
|
@ -67,19 +69,27 @@ use crate::node::CliNodeCodeTranslator;
|
||||||
use crate::node::CliNodeResolver;
|
use crate::node::CliNodeResolver;
|
||||||
use crate::node::CliPackageJsonResolver;
|
use crate::node::CliPackageJsonResolver;
|
||||||
use crate::npm::create_cli_npm_resolver;
|
use crate::npm::create_cli_npm_resolver;
|
||||||
|
use crate::npm::installer::NpmInstaller;
|
||||||
|
use crate::npm::installer::NpmResolutionInstaller;
|
||||||
use crate::npm::CliByonmNpmResolverCreateOptions;
|
use crate::npm::CliByonmNpmResolverCreateOptions;
|
||||||
use crate::npm::CliManagedNpmResolverCreateOptions;
|
use crate::npm::CliManagedNpmResolverCreateOptions;
|
||||||
|
use crate::npm::CliNpmCache;
|
||||||
|
use crate::npm::CliNpmCacheHttpClient;
|
||||||
|
use crate::npm::CliNpmRegistryInfoProvider;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::npm::CliNpmResolverCreateOptions;
|
use crate::npm::CliNpmResolverCreateOptions;
|
||||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||||
|
use crate::npm::CliNpmTarballCache;
|
||||||
use crate::npm::NpmRegistryReadPermissionChecker;
|
use crate::npm::NpmRegistryReadPermissionChecker;
|
||||||
use crate::npm::NpmRegistryReadPermissionCheckerMode;
|
use crate::npm::NpmRegistryReadPermissionCheckerMode;
|
||||||
|
use crate::npm::NpmResolutionInitializer;
|
||||||
use crate::resolver::CjsTracker;
|
use crate::resolver::CjsTracker;
|
||||||
use crate::resolver::CliDenoResolver;
|
use crate::resolver::CliDenoResolver;
|
||||||
|
use crate::resolver::CliNpmGraphResolver;
|
||||||
use crate::resolver::CliNpmReqResolver;
|
use crate::resolver::CliNpmReqResolver;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
use crate::resolver::CliResolverOptions;
|
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
use crate::resolver::CliSloppyImportsResolver;
|
||||||
|
use crate::resolver::FoundPackageJsonDepFlag;
|
||||||
use crate::resolver::NpmModuleLoader;
|
use crate::resolver::NpmModuleLoader;
|
||||||
use crate::standalone::binary::DenoCompileBinaryWriter;
|
use crate::standalone::binary::DenoCompileBinaryWriter;
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
|
@ -188,6 +198,7 @@ struct CliFactoryServices {
|
||||||
emitter: Deferred<Arc<Emitter>>,
|
emitter: Deferred<Arc<Emitter>>,
|
||||||
feature_checker: Deferred<Arc<FeatureChecker>>,
|
feature_checker: Deferred<Arc<FeatureChecker>>,
|
||||||
file_fetcher: Deferred<Arc<CliFileFetcher>>,
|
file_fetcher: Deferred<Arc<CliFileFetcher>>,
|
||||||
|
found_pkg_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
|
||||||
fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
|
fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
|
||||||
global_http_cache: Deferred<Arc<GlobalHttpCache>>,
|
global_http_cache: Deferred<Arc<GlobalHttpCache>>,
|
||||||
http_cache: Deferred<Arc<dyn HttpCache>>,
|
http_cache: Deferred<Arc<dyn HttpCache>>,
|
||||||
|
@ -202,9 +213,18 @@ struct CliFactoryServices {
|
||||||
module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
|
module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
|
||||||
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
|
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
|
||||||
node_resolver: Deferred<Arc<CliNodeResolver>>,
|
node_resolver: Deferred<Arc<CliNodeResolver>>,
|
||||||
|
npm_cache: Deferred<Arc<CliNpmCache>>,
|
||||||
npm_cache_dir: Deferred<Arc<NpmCacheDir>>,
|
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_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_resolver: Deferred<Arc<dyn CliNpmResolver>>,
|
||||||
|
npm_tarball_cache: Deferred<Arc<CliNpmTarballCache>>,
|
||||||
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
|
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
|
||||||
permission_desc_parser:
|
permission_desc_parser:
|
||||||
Deferred<Arc<RuntimePermissionDescriptorParser<CliSys>>>,
|
Deferred<Arc<RuntimePermissionDescriptorParser<CliSys>>>,
|
||||||
|
@ -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> {
|
pub fn npm_cache_dir(&self) -> Result<&Arc<NpmCacheDir>, AnyError> {
|
||||||
self.services.npm_cache_dir.get_or_try_init(|| {
|
self.services.npm_cache_dir.get_or_try_init(|| {
|
||||||
let global_path = self.deno_dir()?.npm_folder_path();
|
let global_path = self.deno_dir()?.npm_folder_path();
|
||||||
|
@ -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(
|
pub async fn npm_resolver(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<&Arc<dyn CliNpmResolver>, AnyError> {
|
) -> Result<&Arc<dyn CliNpmResolver>, AnyError> {
|
||||||
|
@ -419,7 +568,7 @@ impl CliFactory {
|
||||||
.get_or_try_init_async(
|
.get_or_try_init_async(
|
||||||
async {
|
async {
|
||||||
let cli_options = self.cli_options()?;
|
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(
|
CliNpmResolverCreateOptions::Byonm(
|
||||||
CliByonmNpmResolverCreateOptions {
|
CliByonmNpmResolverCreateOptions {
|
||||||
sys: self.sys(),
|
sys: self.sys(),
|
||||||
|
@ -438,52 +587,43 @@ impl CliFactory {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
self
|
||||||
|
.npm_resolution_initializer()?
|
||||||
|
.ensure_initialized()
|
||||||
|
.await?;
|
||||||
CliNpmResolverCreateOptions::Managed(
|
CliNpmResolverCreateOptions::Managed(
|
||||||
CliManagedNpmResolverCreateOptions {
|
CliManagedNpmResolverCreateOptions {
|
||||||
http_client_provider: self.http_client_provider().clone(),
|
|
||||||
npm_install_deps_provider: Arc::new(
|
|
||||||
NpmInstallDepsProvider::from_workspace(
|
|
||||||
cli_options.workspace(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
sys: self.sys(),
|
sys: self.sys(),
|
||||||
snapshot: match cli_options.resolve_npm_resolution_snapshot()? {
|
npm_resolution: self.npm_resolution().clone(),
|
||||||
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_cache_dir: self.npm_cache_dir()?.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
|
maybe_node_modules_path: cli_options
|
||||||
.node_modules_dir_path()
|
.node_modules_dir_path()
|
||||||
.cloned(),
|
.cloned(),
|
||||||
npm_system_info: cli_options.npm_system_info(),
|
npm_system_info: cli_options.npm_system_info(),
|
||||||
npmrc: cli_options.npmrc().clone(),
|
npmrc: cli_options.npmrc().clone(),
|
||||||
lifecycle_scripts: cli_options.lifecycle_scripts_config(),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
}))
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
.boxed_local(),
|
.boxed_local(),
|
||||||
)
|
)
|
||||||
.await
|
.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(
|
pub fn sloppy_imports_resolver(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<&Arc<CliSloppyImportsResolver>>, AnyError> {
|
) -> Result<Option<&Arc<CliSloppyImportsResolver>>, AnyError> {
|
||||||
|
@ -571,17 +711,10 @@ impl CliFactory {
|
||||||
.resolver
|
.resolver
|
||||||
.get_or_try_init_async(
|
.get_or_try_init_async(
|
||||||
async {
|
async {
|
||||||
let cli_options = self.cli_options()?;
|
Ok(Arc::new(CliResolver::new(
|
||||||
Ok(Arc::new(CliResolver::new(CliResolverOptions {
|
self.deno_resolver().await?.clone(),
|
||||||
npm_resolver: if cli_options.no_npm() {
|
self.services.found_pkg_json_dep_flag.clone(),
|
||||||
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(),
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
.boxed_local(),
|
.boxed_local(),
|
||||||
)
|
)
|
||||||
|
@ -752,6 +885,7 @@ impl CliFactory {
|
||||||
cli_options.clone(),
|
cli_options.clone(),
|
||||||
self.module_graph_builder().await?.clone(),
|
self.module_graph_builder().await?.clone(),
|
||||||
self.node_resolver().await?.clone(),
|
self.node_resolver().await?.clone(),
|
||||||
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
self.npm_resolver().await?.clone(),
|
self.npm_resolver().await?.clone(),
|
||||||
self.sys(),
|
self.sys(),
|
||||||
)))
|
)))
|
||||||
|
@ -777,6 +911,8 @@ impl CliFactory {
|
||||||
cli_options.maybe_lockfile().cloned(),
|
cli_options.maybe_lockfile().cloned(),
|
||||||
self.maybe_file_watcher_reporter().clone(),
|
self.maybe_file_watcher_reporter().clone(),
|
||||||
self.module_info_cache()?.clone(),
|
self.module_info_cache()?.clone(),
|
||||||
|
self.npm_graph_resolver()?.clone(),
|
||||||
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
self.npm_resolver().await?.clone(),
|
self.npm_resolver().await?.clone(),
|
||||||
self.parsed_source_cache().clone(),
|
self.parsed_source_cache().clone(),
|
||||||
self.resolver().await?.clone(),
|
self.resolver().await?.clone(),
|
||||||
|
@ -797,7 +933,7 @@ impl CliFactory {
|
||||||
let cli_options = self.cli_options()?;
|
let cli_options = self.cli_options()?;
|
||||||
Ok(Arc::new(ModuleGraphCreator::new(
|
Ok(Arc::new(ModuleGraphCreator::new(
|
||||||
cli_options.clone(),
|
cli_options.clone(),
|
||||||
self.npm_resolver().await?.clone(),
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
self.module_graph_builder().await?.clone(),
|
self.module_graph_builder().await?.clone(),
|
||||||
self.type_checker().await?.clone(),
|
self.type_checker().await?.clone(),
|
||||||
)))
|
)))
|
||||||
|
@ -997,6 +1133,7 @@ impl CliFactory {
|
||||||
self.sys(),
|
self.sys(),
|
||||||
)),
|
)),
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
npm_resolver.clone(),
|
npm_resolver.clone(),
|
||||||
pkg_json_resolver,
|
pkg_json_resolver,
|
||||||
self.root_cert_store_provider().clone(),
|
self.root_cert_store_provider().clone(),
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use deno_config::deno_json;
|
use deno_config::deno_json;
|
||||||
use deno_config::deno_json::JsxImportSourceConfig;
|
use deno_config::deno_json::JsxImportSourceConfig;
|
||||||
|
use deno_config::deno_json::NodeModulesDirMode;
|
||||||
use deno_config::workspace::JsrPackageConfig;
|
use deno_config::workspace::JsrPackageConfig;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
|
@ -51,8 +52,11 @@ use crate::cache::ModuleInfoCache;
|
||||||
use crate::cache::ParsedSourceCache;
|
use crate::cache::ParsedSourceCache;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::file_fetcher::CliFileFetcher;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
|
use crate::npm::installer::NpmInstaller;
|
||||||
|
use crate::npm::installer::PackageCaching;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::resolver::CjsTracker;
|
use crate::resolver::CjsTracker;
|
||||||
|
use crate::resolver::CliNpmGraphResolver;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
use crate::resolver::CliSloppyImportsResolver;
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
|
@ -263,7 +267,7 @@ pub struct CreateGraphOptions<'a> {
|
||||||
|
|
||||||
pub struct ModuleGraphCreator {
|
pub struct ModuleGraphCreator {
|
||||||
options: Arc<CliOptions>,
|
options: Arc<CliOptions>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||||
type_checker: Arc<TypeChecker>,
|
type_checker: Arc<TypeChecker>,
|
||||||
}
|
}
|
||||||
|
@ -271,13 +275,13 @@ pub struct ModuleGraphCreator {
|
||||||
impl ModuleGraphCreator {
|
impl ModuleGraphCreator {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
options: Arc<CliOptions>,
|
options: Arc<CliOptions>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||||
type_checker: Arc<TypeChecker>,
|
type_checker: Arc<TypeChecker>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
options,
|
options,
|
||||||
npm_resolver,
|
npm_installer,
|
||||||
module_graph_builder,
|
module_graph_builder,
|
||||||
type_checker,
|
type_checker,
|
||||||
}
|
}
|
||||||
|
@ -400,9 +404,9 @@ impl ModuleGraphCreator {
|
||||||
.build_graph_with_npm_resolution(&mut graph, options)
|
.build_graph_with_npm_resolution(&mut graph, options)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if let Some(npm_resolver) = self.npm_resolver.as_managed() {
|
if let Some(npm_installer) = &self.npm_installer {
|
||||||
if graph.has_node_specifier && self.options.type_check_mode().is_true() {
|
if graph.has_node_specifier && self.options.type_check_mode().is_true() {
|
||||||
npm_resolver.inject_synthetic_types_node_package().await?;
|
npm_installer.inject_synthetic_types_node_package().await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +501,8 @@ pub struct ModuleGraphBuilder {
|
||||||
lockfile: Option<Arc<CliLockfile>>,
|
lockfile: Option<Arc<CliLockfile>>,
|
||||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
module_info_cache: Arc<ModuleInfoCache>,
|
||||||
|
npm_graph_resolver: Arc<CliNpmGraphResolver>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||||
resolver: Arc<CliResolver>,
|
resolver: Arc<CliResolver>,
|
||||||
|
@ -516,6 +522,8 @@ impl ModuleGraphBuilder {
|
||||||
lockfile: Option<Arc<CliLockfile>>,
|
lockfile: Option<Arc<CliLockfile>>,
|
||||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
module_info_cache: Arc<ModuleInfoCache>,
|
||||||
|
npm_graph_resolver: Arc<CliNpmGraphResolver>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||||
resolver: Arc<CliResolver>,
|
resolver: Arc<CliResolver>,
|
||||||
|
@ -532,6 +540,8 @@ impl ModuleGraphBuilder {
|
||||||
lockfile,
|
lockfile,
|
||||||
maybe_file_watcher_reporter,
|
maybe_file_watcher_reporter,
|
||||||
module_info_cache,
|
module_info_cache,
|
||||||
|
npm_graph_resolver,
|
||||||
|
npm_installer,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
parsed_source_cache,
|
parsed_source_cache,
|
||||||
resolver,
|
resolver,
|
||||||
|
@ -630,10 +640,7 @@ impl ModuleGraphBuilder {
|
||||||
Some(loader) => MutLoaderRef::Borrowed(loader),
|
Some(loader) => MutLoaderRef::Borrowed(loader),
|
||||||
None => MutLoaderRef::Owned(self.create_graph_loader()),
|
None => MutLoaderRef::Owned(self.create_graph_loader()),
|
||||||
};
|
};
|
||||||
let cli_resolver = &self.resolver;
|
|
||||||
let graph_resolver = self.create_graph_resolver()?;
|
let graph_resolver = self.create_graph_resolver()?;
|
||||||
let graph_npm_resolver =
|
|
||||||
cli_resolver.create_graph_npm_resolver(options.npm_caching);
|
|
||||||
let maybe_file_watcher_reporter = self
|
let maybe_file_watcher_reporter = self
|
||||||
.maybe_file_watcher_reporter
|
.maybe_file_watcher_reporter
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -654,7 +661,7 @@ impl ModuleGraphBuilder {
|
||||||
executor: Default::default(),
|
executor: Default::default(),
|
||||||
file_system: &self.sys,
|
file_system: &self.sys,
|
||||||
jsr_url_provider: &CliJsrUrlProvider,
|
jsr_url_provider: &CliJsrUrlProvider,
|
||||||
npm_resolver: Some(&graph_npm_resolver),
|
npm_resolver: Some(self.npm_graph_resolver.as_ref()),
|
||||||
module_analyzer: &analyzer,
|
module_analyzer: &analyzer,
|
||||||
reporter: maybe_file_watcher_reporter,
|
reporter: maybe_file_watcher_reporter,
|
||||||
resolver: Some(&graph_resolver),
|
resolver: Some(&graph_resolver),
|
||||||
|
@ -678,16 +685,15 @@ impl ModuleGraphBuilder {
|
||||||
if self
|
if self
|
||||||
.cli_options
|
.cli_options
|
||||||
.node_modules_dir()?
|
.node_modules_dir()?
|
||||||
.map(|m| m.uses_node_modules_dir())
|
.map(|m| m == NodeModulesDirMode::Auto)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
if let Some(npm_resolver) = self.npm_resolver.as_managed() {
|
if let Some(npm_installer) = &self.npm_installer {
|
||||||
let already_done =
|
let already_done = npm_installer
|
||||||
npm_resolver.ensure_top_level_package_json_install().await?;
|
.ensure_top_level_package_json_install()
|
||||||
|
.await?;
|
||||||
if !already_done && matches!(npm_caching, NpmCachingStrategy::Eager) {
|
if !already_done && matches!(npm_caching, NpmCachingStrategy::Eager) {
|
||||||
npm_resolver
|
npm_installer.cache_packages(PackageCaching::All).await?;
|
||||||
.cache_packages(crate::npm::PackageCaching::All)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -775,11 +781,7 @@ impl ModuleGraphBuilder {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let parser = self.parsed_source_cache.as_capturing_parser();
|
let parser = self.parsed_source_cache.as_capturing_parser();
|
||||||
let cli_resolver = &self.resolver;
|
|
||||||
let graph_resolver = self.create_graph_resolver()?;
|
let graph_resolver = self.create_graph_resolver()?;
|
||||||
let graph_npm_resolver = cli_resolver.create_graph_npm_resolver(
|
|
||||||
self.cli_options.default_npm_caching_strategy(),
|
|
||||||
);
|
|
||||||
|
|
||||||
graph.build_fast_check_type_graph(
|
graph.build_fast_check_type_graph(
|
||||||
deno_graph::BuildFastCheckTypeGraphOptions {
|
deno_graph::BuildFastCheckTypeGraphOptions {
|
||||||
|
@ -788,7 +790,7 @@ impl ModuleGraphBuilder {
|
||||||
fast_check_dts: false,
|
fast_check_dts: false,
|
||||||
jsr_url_provider: &CliJsrUrlProvider,
|
jsr_url_provider: &CliJsrUrlProvider,
|
||||||
resolver: Some(&graph_resolver),
|
resolver: Some(&graph_resolver),
|
||||||
npm_resolver: Some(&graph_npm_resolver),
|
npm_resolver: Some(self.npm_graph_resolver.as_ref()),
|
||||||
workspace_fast_check: options.workspace_fast_check,
|
workspace_fast_check: options.workspace_fast_check,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -480,7 +480,7 @@ impl Document {
|
||||||
let is_cjs_resolver =
|
let is_cjs_resolver =
|
||||||
resolver.as_is_cjs_resolver(self.file_referrer.as_ref());
|
resolver.as_is_cjs_resolver(self.file_referrer.as_ref());
|
||||||
let npm_resolver =
|
let npm_resolver =
|
||||||
resolver.create_graph_npm_resolver(self.file_referrer.as_ref());
|
resolver.as_graph_npm_resolver(self.file_referrer.as_ref());
|
||||||
let config_data = resolver.as_config_data(self.file_referrer.as_ref());
|
let config_data = resolver.as_config_data(self.file_referrer.as_ref());
|
||||||
let jsx_import_source_config =
|
let jsx_import_source_config =
|
||||||
config_data.and_then(|d| d.maybe_jsx_import_source_config());
|
config_data.and_then(|d| d.maybe_jsx_import_source_config());
|
||||||
|
@ -503,7 +503,7 @@ impl Document {
|
||||||
s,
|
s,
|
||||||
&CliJsrUrlProvider,
|
&CliJsrUrlProvider,
|
||||||
Some(&resolver),
|
Some(&resolver),
|
||||||
Some(&npm_resolver),
|
Some(npm_resolver.as_ref()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -513,7 +513,7 @@ impl Document {
|
||||||
Arc::new(d.with_new_resolver(
|
Arc::new(d.with_new_resolver(
|
||||||
&CliJsrUrlProvider,
|
&CliJsrUrlProvider,
|
||||||
Some(&resolver),
|
Some(&resolver),
|
||||||
Some(&npm_resolver),
|
Some(npm_resolver.as_ref()),
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
is_script = self.is_script;
|
is_script = self.is_script;
|
||||||
|
@ -1702,7 +1702,7 @@ fn analyze_module(
|
||||||
) -> (ModuleResult, ResolutionMode) {
|
) -> (ModuleResult, ResolutionMode) {
|
||||||
match parsed_source_result {
|
match parsed_source_result {
|
||||||
Ok(parsed_source) => {
|
Ok(parsed_source) => {
|
||||||
let npm_resolver = resolver.create_graph_npm_resolver(file_referrer);
|
let npm_resolver = resolver.as_graph_npm_resolver(file_referrer);
|
||||||
let cli_resolver = resolver.as_cli_resolver(file_referrer);
|
let cli_resolver = resolver.as_cli_resolver(file_referrer);
|
||||||
let is_cjs_resolver = resolver.as_is_cjs_resolver(file_referrer);
|
let is_cjs_resolver = resolver.as_is_cjs_resolver(file_referrer);
|
||||||
let config_data = resolver.as_config_data(file_referrer);
|
let config_data = resolver.as_config_data(file_referrer);
|
||||||
|
@ -1731,7 +1731,7 @@ fn analyze_module(
|
||||||
file_system: &deno_graph::source::NullFileSystem,
|
file_system: &deno_graph::source::NullFileSystem,
|
||||||
jsr_url_provider: &CliJsrUrlProvider,
|
jsr_url_provider: &CliJsrUrlProvider,
|
||||||
maybe_resolver: Some(&resolver),
|
maybe_resolver: Some(&resolver),
|
||||||
maybe_npm_resolver: Some(&npm_resolver),
|
maybe_npm_resolver: Some(npm_resolver.as_ref()),
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
module_resolution_mode,
|
module_resolution_mode,
|
||||||
|
|
|
@ -9,7 +9,6 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_cache_dir::file_fetcher::CacheSetting;
|
|
||||||
use deno_cache_dir::npm::NpmCacheDir;
|
use deno_cache_dir::npm::NpmCacheDir;
|
||||||
use deno_cache_dir::HttpCache;
|
use deno_cache_dir::HttpCache;
|
||||||
use deno_config::deno_json::JsxImportSourceConfig;
|
use deno_config::deno_json::JsxImportSourceConfig;
|
||||||
|
@ -21,9 +20,11 @@ use deno_graph::GraphImport;
|
||||||
use deno_graph::ModuleSpecifier;
|
use deno_graph::ModuleSpecifier;
|
||||||
use deno_graph::Range;
|
use deno_graph::Range;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
|
use deno_npm_cache::TarballCache;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
use deno_resolver::cjs::IsCjsResolutionMode;
|
use deno_resolver::cjs::IsCjsResolutionMode;
|
||||||
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
|
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
|
||||||
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
||||||
use deno_resolver::npm::NpmReqResolverOptions;
|
use deno_resolver::npm::NpmReqResolverOptions;
|
||||||
use deno_resolver::DenoResolverOptions;
|
use deno_resolver::DenoResolverOptions;
|
||||||
|
@ -42,6 +43,8 @@ use super::cache::LspCache;
|
||||||
use super::jsr::JsrCacheResolver;
|
use super::jsr::JsrCacheResolver;
|
||||||
use crate::args::create_default_npmrc;
|
use crate::args::create_default_npmrc;
|
||||||
use crate::args::CliLockfile;
|
use crate::args::CliLockfile;
|
||||||
|
use crate::args::LifecycleScriptsConfig;
|
||||||
|
use crate::args::NpmCachingStrategy;
|
||||||
use crate::args::NpmInstallDepsProvider;
|
use crate::args::NpmInstallDepsProvider;
|
||||||
use crate::factory::Deferred;
|
use crate::factory::Deferred;
|
||||||
use crate::graph_util::to_node_resolution_kind;
|
use crate::graph_util::to_node_resolution_kind;
|
||||||
|
@ -53,19 +56,25 @@ use crate::lsp::config::ConfigData;
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
use crate::node::CliNodeResolver;
|
use crate::node::CliNodeResolver;
|
||||||
use crate::node::CliPackageJsonResolver;
|
use crate::node::CliPackageJsonResolver;
|
||||||
use crate::npm::create_cli_npm_resolver_for_lsp;
|
use crate::npm::create_cli_npm_resolver;
|
||||||
|
use crate::npm::installer::NpmInstaller;
|
||||||
|
use crate::npm::installer::NpmResolutionInstaller;
|
||||||
use crate::npm::CliByonmNpmResolverCreateOptions;
|
use crate::npm::CliByonmNpmResolverCreateOptions;
|
||||||
use crate::npm::CliManagedNpmResolverCreateOptions;
|
use crate::npm::CliManagedNpmResolverCreateOptions;
|
||||||
|
use crate::npm::CliNpmCache;
|
||||||
|
use crate::npm::CliNpmCacheHttpClient;
|
||||||
|
use crate::npm::CliNpmRegistryInfoProvider;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::npm::CliNpmResolverCreateOptions;
|
use crate::npm::CliNpmResolverCreateOptions;
|
||||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||||
use crate::npm::ManagedCliNpmResolver;
|
use crate::npm::ManagedCliNpmResolver;
|
||||||
|
use crate::npm::NpmResolutionInitializer;
|
||||||
use crate::resolver::CliDenoResolver;
|
use crate::resolver::CliDenoResolver;
|
||||||
|
use crate::resolver::CliNpmGraphResolver;
|
||||||
use crate::resolver::CliNpmReqResolver;
|
use crate::resolver::CliNpmReqResolver;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
use crate::resolver::CliResolverOptions;
|
use crate::resolver::FoundPackageJsonDepFlag;
|
||||||
use crate::resolver::IsCjsResolver;
|
use crate::resolver::IsCjsResolver;
|
||||||
use crate::resolver::WorkerCliNpmGraphResolver;
|
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
use crate::tsc::into_specifier_and_media_type;
|
use crate::tsc::into_specifier_and_media_type;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
|
@ -77,6 +86,8 @@ struct LspScopeResolver {
|
||||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||||
is_cjs_resolver: Arc<IsCjsResolver>,
|
is_cjs_resolver: Arc<IsCjsResolver>,
|
||||||
jsr_resolver: Option<Arc<JsrCacheResolver>>,
|
jsr_resolver: Option<Arc<JsrCacheResolver>>,
|
||||||
|
npm_graph_resolver: Arc<CliNpmGraphResolver>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
||||||
node_resolver: Option<Arc<CliNodeResolver>>,
|
node_resolver: Option<Arc<CliNodeResolver>>,
|
||||||
npm_pkg_req_resolver: Option<Arc<CliNpmReqResolver>>,
|
npm_pkg_req_resolver: Option<Arc<CliNpmReqResolver>>,
|
||||||
|
@ -96,6 +107,8 @@ impl Default for LspScopeResolver {
|
||||||
in_npm_pkg_checker: factory.in_npm_pkg_checker().clone(),
|
in_npm_pkg_checker: factory.in_npm_pkg_checker().clone(),
|
||||||
is_cjs_resolver: factory.is_cjs_resolver().clone(),
|
is_cjs_resolver: factory.is_cjs_resolver().clone(),
|
||||||
jsr_resolver: None,
|
jsr_resolver: None,
|
||||||
|
npm_graph_resolver: factory.npm_graph_resolver().clone(),
|
||||||
|
npm_installer: None,
|
||||||
npm_resolver: None,
|
npm_resolver: None,
|
||||||
node_resolver: None,
|
node_resolver: None,
|
||||||
npm_pkg_req_resolver: None,
|
npm_pkg_req_resolver: None,
|
||||||
|
@ -121,6 +134,7 @@ impl LspScopeResolver {
|
||||||
}
|
}
|
||||||
let in_npm_pkg_checker = factory.in_npm_pkg_checker().clone();
|
let in_npm_pkg_checker = factory.in_npm_pkg_checker().clone();
|
||||||
let npm_resolver = factory.npm_resolver().cloned();
|
let npm_resolver = factory.npm_resolver().cloned();
|
||||||
|
let npm_installer = factory.npm_installer().cloned();
|
||||||
let node_resolver = factory.node_resolver().cloned();
|
let node_resolver = factory.node_resolver().cloned();
|
||||||
let npm_pkg_req_resolver = factory.npm_pkg_req_resolver().cloned();
|
let npm_pkg_req_resolver = factory.npm_pkg_req_resolver().cloned();
|
||||||
let cli_resolver = factory.cli_resolver().clone();
|
let cli_resolver = factory.cli_resolver().clone();
|
||||||
|
@ -133,8 +147,7 @@ impl LspScopeResolver {
|
||||||
cache.for_specifier(config_data.map(|d| d.scope.as_ref())),
|
cache.for_specifier(config_data.map(|d| d.scope.as_ref())),
|
||||||
config_data.and_then(|d| d.lockfile.clone()),
|
config_data.and_then(|d| d.lockfile.clone()),
|
||||||
)));
|
)));
|
||||||
let npm_graph_resolver = cli_resolver
|
let npm_graph_resolver = factory.npm_graph_resolver();
|
||||||
.create_graph_npm_resolver(crate::graph_util::NpmCachingStrategy::Eager);
|
|
||||||
let maybe_jsx_import_source_config =
|
let maybe_jsx_import_source_config =
|
||||||
config_data.and_then(|d| d.maybe_jsx_import_source_config());
|
config_data.and_then(|d| d.maybe_jsx_import_source_config());
|
||||||
let graph_imports = config_data
|
let graph_imports = config_data
|
||||||
|
@ -156,7 +169,7 @@ impl LspScopeResolver {
|
||||||
imports,
|
imports,
|
||||||
&CliJsrUrlProvider,
|
&CliJsrUrlProvider,
|
||||||
Some(&resolver),
|
Some(&resolver),
|
||||||
Some(&npm_graph_resolver),
|
Some(npm_graph_resolver.as_ref()),
|
||||||
);
|
);
|
||||||
(referrer, graph_import)
|
(referrer, graph_import)
|
||||||
})
|
})
|
||||||
|
@ -207,8 +220,10 @@ impl LspScopeResolver {
|
||||||
in_npm_pkg_checker,
|
in_npm_pkg_checker,
|
||||||
is_cjs_resolver: factory.is_cjs_resolver().clone(),
|
is_cjs_resolver: factory.is_cjs_resolver().clone(),
|
||||||
jsr_resolver,
|
jsr_resolver,
|
||||||
|
npm_graph_resolver: factory.npm_graph_resolver().clone(),
|
||||||
npm_pkg_req_resolver,
|
npm_pkg_req_resolver,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
|
npm_installer,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
pkg_json_resolver,
|
pkg_json_resolver,
|
||||||
redirect_resolver,
|
redirect_resolver,
|
||||||
|
@ -231,6 +246,9 @@ impl LspScopeResolver {
|
||||||
in_npm_pkg_checker: factory.in_npm_pkg_checker().clone(),
|
in_npm_pkg_checker: factory.in_npm_pkg_checker().clone(),
|
||||||
is_cjs_resolver: factory.is_cjs_resolver().clone(),
|
is_cjs_resolver: factory.is_cjs_resolver().clone(),
|
||||||
jsr_resolver: self.jsr_resolver.clone(),
|
jsr_resolver: self.jsr_resolver.clone(),
|
||||||
|
npm_graph_resolver: factory.npm_graph_resolver().clone(),
|
||||||
|
// npm installer isn't necessary for a snapshot
|
||||||
|
npm_installer: None,
|
||||||
npm_pkg_req_resolver: factory.npm_pkg_req_resolver().cloned(),
|
npm_pkg_req_resolver: factory.npm_pkg_req_resolver().cloned(),
|
||||||
npm_resolver: factory.npm_resolver().cloned(),
|
npm_resolver: factory.npm_resolver().cloned(),
|
||||||
node_resolver: factory.node_resolver().cloned(),
|
node_resolver: factory.node_resolver().cloned(),
|
||||||
|
@ -318,14 +336,12 @@ impl LspResolver {
|
||||||
if let Some(dep_info) = dep_info {
|
if let Some(dep_info) = dep_info {
|
||||||
*resolver.dep_info.lock() = dep_info.clone();
|
*resolver.dep_info.lock() = dep_info.clone();
|
||||||
}
|
}
|
||||||
if let Some(npm_resolver) = resolver.npm_resolver.as_ref() {
|
if let Some(npm_installer) = resolver.npm_installer.as_ref() {
|
||||||
if let Some(npm_resolver) = npm_resolver.as_managed() {
|
let reqs = dep_info
|
||||||
let reqs = dep_info
|
.map(|i| i.npm_reqs.iter().cloned().collect::<Vec<_>>())
|
||||||
.map(|i| i.npm_reqs.iter().cloned().collect::<Vec<_>>())
|
.unwrap_or_default();
|
||||||
.unwrap_or_default();
|
if let Err(err) = npm_installer.set_package_reqs(&reqs).await {
|
||||||
if let Err(err) = npm_resolver.set_package_reqs(&reqs).await {
|
lsp_warn!("Could not set npm package requirements: {:#}", err);
|
||||||
lsp_warn!("Could not set npm package requirements: {:#}", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,14 +355,12 @@ impl LspResolver {
|
||||||
resolver.resolver.as_ref()
|
resolver.resolver.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_graph_npm_resolver(
|
pub fn as_graph_npm_resolver(
|
||||||
&self,
|
&self,
|
||||||
file_referrer: Option<&ModuleSpecifier>,
|
file_referrer: Option<&ModuleSpecifier>,
|
||||||
) -> WorkerCliNpmGraphResolver {
|
) -> &Arc<CliNpmGraphResolver> {
|
||||||
let resolver = self.get_scope_resolver(file_referrer);
|
let resolver = self.get_scope_resolver(file_referrer);
|
||||||
resolver
|
&resolver.npm_graph_resolver
|
||||||
.resolver
|
|
||||||
.create_graph_npm_resolver(crate::graph_util::NpmCachingStrategy::Eager)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_is_cjs_resolver(
|
pub fn as_is_cjs_resolver(
|
||||||
|
@ -590,9 +604,12 @@ pub struct ScopeDepInfo {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ResolverFactoryServices {
|
struct ResolverFactoryServices {
|
||||||
cli_resolver: Deferred<Arc<CliResolver>>,
|
cli_resolver: Deferred<Arc<CliResolver>>,
|
||||||
|
found_pkg_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
|
||||||
in_npm_pkg_checker: Deferred<Arc<dyn InNpmPackageChecker>>,
|
in_npm_pkg_checker: Deferred<Arc<dyn InNpmPackageChecker>>,
|
||||||
is_cjs_resolver: Deferred<Arc<IsCjsResolver>>,
|
is_cjs_resolver: Deferred<Arc<IsCjsResolver>>,
|
||||||
node_resolver: Deferred<Option<Arc<CliNodeResolver>>>,
|
node_resolver: Deferred<Option<Arc<CliNodeResolver>>>,
|
||||||
|
npm_graph_resolver: Deferred<Arc<CliNpmGraphResolver>>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
npm_pkg_req_resolver: Deferred<Option<Arc<CliNpmReqResolver>>>,
|
npm_pkg_req_resolver: Deferred<Option<Arc<CliNpmReqResolver>>>,
|
||||||
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
||||||
}
|
}
|
||||||
|
@ -616,6 +633,10 @@ impl<'a> ResolverFactory<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo(dsherret): probably this method could be removed in the future
|
||||||
|
// and instead just `npm_resolution_initializer.ensure_initialized()` could
|
||||||
|
// be called. The reason this exists is because creating the npm resolvers
|
||||||
|
// used to be async.
|
||||||
async fn init_npm_resolver(
|
async fn init_npm_resolver(
|
||||||
&mut self,
|
&mut self,
|
||||||
http_client_provider: &Arc<HttpClientProvider>,
|
http_client_provider: &Arc<HttpClientProvider>,
|
||||||
|
@ -645,11 +666,31 @@ impl<'a> ResolverFactory<'a> {
|
||||||
cache.deno_dir().npm_folder_path(),
|
cache.deno_dir().npm_folder_path(),
|
||||||
npmrc.get_all_known_registries_urls(),
|
npmrc.get_all_known_registries_urls(),
|
||||||
));
|
));
|
||||||
CliNpmResolverCreateOptions::Managed(CliManagedNpmResolverCreateOptions {
|
let npm_cache = Arc::new(CliNpmCache::new(
|
||||||
http_client_provider: http_client_provider.clone(),
|
npm_cache_dir.clone(),
|
||||||
// only used for top level install, so we can ignore this
|
sys.clone(),
|
||||||
npm_install_deps_provider: Arc::new(NpmInstallDepsProvider::empty()),
|
// Use an "only" cache setting in order to make the
|
||||||
snapshot: match self.config_data.and_then(|d| d.lockfile.as_ref()) {
|
// user do an explicit "cache" command and prevent
|
||||||
|
// the cache from being filled with lots of packages while
|
||||||
|
// the user is typing.
|
||||||
|
deno_npm_cache::NpmCacheSetting::Only,
|
||||||
|
npmrc.clone(),
|
||||||
|
));
|
||||||
|
let pb = ProgressBar::new(ProgressBarStyle::TextOnly);
|
||||||
|
let npm_client = Arc::new(CliNpmCacheHttpClient::new(
|
||||||
|
http_client_provider.clone(),
|
||||||
|
pb.clone(),
|
||||||
|
));
|
||||||
|
let registry_info_provider = Arc::new(CliNpmRegistryInfoProvider::new(
|
||||||
|
npm_cache.clone(),
|
||||||
|
npm_client.clone(),
|
||||||
|
npmrc.clone(),
|
||||||
|
));
|
||||||
|
let npm_resolution = Arc::new(NpmResolutionCell::default());
|
||||||
|
let npm_resolution_initializer = Arc::new(NpmResolutionInitializer::new(
|
||||||
|
registry_info_provider.clone(),
|
||||||
|
npm_resolution.clone(),
|
||||||
|
match self.config_data.and_then(|d| d.lockfile.as_ref()) {
|
||||||
Some(lockfile) => {
|
Some(lockfile) => {
|
||||||
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
|
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
|
||||||
lockfile.clone(),
|
lockfile.clone(),
|
||||||
|
@ -657,26 +698,62 @@ impl<'a> ResolverFactory<'a> {
|
||||||
}
|
}
|
||||||
None => CliNpmResolverManagedSnapshotOption::Specified(None),
|
None => CliNpmResolverManagedSnapshotOption::Specified(None),
|
||||||
},
|
},
|
||||||
|
));
|
||||||
|
// Don't provide the lockfile. We don't want these resolvers
|
||||||
|
// updating it. Only the cache request should update the lockfile.
|
||||||
|
let maybe_lockfile: Option<Arc<CliLockfile>> = None;
|
||||||
|
let maybe_node_modules_path =
|
||||||
|
self.config_data.and_then(|d| d.node_modules_dir.clone());
|
||||||
|
let tarball_cache = Arc::new(TarballCache::new(
|
||||||
|
npm_cache.clone(),
|
||||||
|
npm_client.clone(),
|
||||||
|
sys.clone(),
|
||||||
|
npmrc.clone(),
|
||||||
|
));
|
||||||
|
let npm_resolution_installer = Arc::new(NpmResolutionInstaller::new(
|
||||||
|
registry_info_provider,
|
||||||
|
npm_resolution.clone(),
|
||||||
|
maybe_lockfile.clone(),
|
||||||
|
));
|
||||||
|
let npm_installer = Arc::new(NpmInstaller::new(
|
||||||
|
npm_cache.clone(),
|
||||||
|
Arc::new(NpmInstallDepsProvider::empty()),
|
||||||
|
npm_resolution.clone(),
|
||||||
|
npm_resolution_initializer.clone(),
|
||||||
|
npm_resolution_installer,
|
||||||
|
&pb,
|
||||||
|
sys.clone(),
|
||||||
|
tarball_cache.clone(),
|
||||||
|
maybe_lockfile,
|
||||||
|
maybe_node_modules_path.clone(),
|
||||||
|
LifecycleScriptsConfig::default(),
|
||||||
|
NpmSystemInfo::default(),
|
||||||
|
));
|
||||||
|
self.set_npm_installer(npm_installer);
|
||||||
|
// spawn due to the lsp's `Send` requirement
|
||||||
|
deno_core::unsync::spawn(async move {
|
||||||
|
if let Err(err) = npm_resolution_initializer.ensure_initialized().await
|
||||||
|
{
|
||||||
|
log::warn!("failed to initialize npm resolution: {}", err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
CliNpmResolverCreateOptions::Managed(CliManagedNpmResolverCreateOptions {
|
||||||
sys: CliSys::default(),
|
sys: CliSys::default(),
|
||||||
npm_cache_dir,
|
npm_cache_dir,
|
||||||
// Use an "only" cache setting in order to make the
|
maybe_node_modules_path,
|
||||||
// user do an explicit "cache" command and prevent
|
|
||||||
// the cache from being filled with lots of packages while
|
|
||||||
// the user is typing.
|
|
||||||
cache_setting: CacheSetting::Only,
|
|
||||||
text_only_progress_bar: ProgressBar::new(ProgressBarStyle::TextOnly),
|
|
||||||
// Don't provide the lockfile. We don't want these resolvers
|
|
||||||
// updating it. Only the cache request should update the lockfile.
|
|
||||||
maybe_lockfile: None,
|
|
||||||
maybe_node_modules_path: self
|
|
||||||
.config_data
|
|
||||||
.and_then(|d| d.node_modules_dir.clone()),
|
|
||||||
npmrc,
|
npmrc,
|
||||||
|
npm_resolution,
|
||||||
npm_system_info: NpmSystemInfo::default(),
|
npm_system_info: NpmSystemInfo::default(),
|
||||||
lifecycle_scripts: Default::default(),
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
self.set_npm_resolver(create_cli_npm_resolver_for_lsp(options).await);
|
self.set_npm_resolver(create_cli_npm_resolver(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_npm_installer(&mut self, npm_installer: Arc<NpmInstaller>) {
|
||||||
|
self.services.npm_installer = Some(npm_installer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_npm_resolver(&mut self, npm_resolver: Arc<dyn CliNpmResolver>) {
|
pub fn set_npm_resolver(&mut self, npm_resolver: Arc<dyn CliNpmResolver>) {
|
||||||
|
@ -720,13 +797,27 @@ impl<'a> ResolverFactory<'a> {
|
||||||
is_byonm: self.config_data.map(|d| d.byonm).unwrap_or(false),
|
is_byonm: self.config_data.map(|d| d.byonm).unwrap_or(false),
|
||||||
maybe_vendor_dir: self.config_data.and_then(|d| d.vendor_dir.as_ref()),
|
maybe_vendor_dir: self.config_data.and_then(|d| d.vendor_dir.as_ref()),
|
||||||
}));
|
}));
|
||||||
Arc::new(CliResolver::new(CliResolverOptions {
|
Arc::new(CliResolver::new(
|
||||||
deno_resolver,
|
deno_resolver,
|
||||||
npm_resolver: self.npm_resolver().cloned(),
|
self.services.found_pkg_json_dep_flag.clone(),
|
||||||
bare_node_builtins_enabled: self
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_installer(&self) -> Option<&Arc<NpmInstaller>> {
|
||||||
|
self.services.npm_installer.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_graph_resolver(&self) -> &Arc<CliNpmGraphResolver> {
|
||||||
|
self.services.npm_graph_resolver.get_or_init(|| {
|
||||||
|
Arc::new(CliNpmGraphResolver::new(
|
||||||
|
None,
|
||||||
|
self.services.found_pkg_json_dep_flag.clone(),
|
||||||
|
self
|
||||||
.config_data
|
.config_data
|
||||||
.is_some_and(|d| d.unstable.contains("bare-node-builtins")),
|
.is_some_and(|d| d.unstable.contains("bare-node-builtins")),
|
||||||
}))
|
NpmCachingStrategy::Eager,
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
cli/main.rs
12
cli/main.rs
|
@ -40,7 +40,6 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::error::CoreError;
|
use deno_core::error::CoreError;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::unsync::JoinHandle;
|
use deno_core::unsync::JoinHandle;
|
||||||
use deno_npm::resolution::SnapshotFromLockfileError;
|
|
||||||
use deno_resolver::npm::ByonmResolvePkgFolderFromDenoReqError;
|
use deno_resolver::npm::ByonmResolvePkgFolderFromDenoReqError;
|
||||||
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
|
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
|
||||||
use deno_runtime::fmt_errors::format_js_error;
|
use deno_runtime::fmt_errors::format_js_error;
|
||||||
|
@ -52,6 +51,7 @@ use factory::CliFactory;
|
||||||
use standalone::MODULE_NOT_FOUND;
|
use standalone::MODULE_NOT_FOUND;
|
||||||
use standalone::UNSUPPORTED_SCHEME;
|
use standalone::UNSUPPORTED_SCHEME;
|
||||||
|
|
||||||
|
use self::npm::ResolveSnapshotError;
|
||||||
use crate::args::flags_from_vec;
|
use crate::args::flags_from_vec;
|
||||||
use crate::args::DenoSubcommand;
|
use crate::args::DenoSubcommand;
|
||||||
use crate::args::Flags;
|
use crate::args::Flags;
|
||||||
|
@ -376,13 +376,15 @@ fn exit_for_error(error: AnyError) -> ! {
|
||||||
util::result::any_and_jserrorbox_downcast_ref::<CoreError>(&error)
|
util::result::any_and_jserrorbox_downcast_ref::<CoreError>(&error)
|
||||||
{
|
{
|
||||||
error_string = format_js_error(e);
|
error_string = format_js_error(e);
|
||||||
} else if let Some(SnapshotFromLockfileError::IntegrityCheckFailed(e)) =
|
} else if let Some(e @ ResolveSnapshotError { .. }) =
|
||||||
util::result::any_and_jserrorbox_downcast_ref::<SnapshotFromLockfileError>(
|
util::result::any_and_jserrorbox_downcast_ref::<ResolveSnapshotError>(
|
||||||
&error,
|
&error,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
error_string = e.to_string();
|
if let Some(e) = e.maybe_integrity_check_error() {
|
||||||
error_code = 10;
|
error_string = e.to_string();
|
||||||
|
error_code = 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_with_message(&error_string, error_code);
|
exit_with_message(&error_string, error_code);
|
||||||
|
|
|
@ -8,8 +8,7 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use deno_npm::resolution::NpmResolutionSnapshot;
|
use deno_npm::resolution::NpmResolutionSnapshot;
|
||||||
use deno_npm::NpmPackageId;
|
use deno_npm::NpmPackageId;
|
||||||
|
use deno_npm::NpmResolutionPackage;
|
||||||
use crate::npm::managed::NpmResolutionPackage;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BinEntries<'a> {
|
pub struct BinEntries<'a> {
|
|
@ -3,14 +3,14 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
|
|
||||||
use crate::npm::PackageCaching;
|
use super::PackageCaching;
|
||||||
|
|
||||||
pub mod bin_entries;
|
pub mod bin_entries;
|
||||||
pub mod lifecycle_scripts;
|
pub mod lifecycle_scripts;
|
||||||
|
|
||||||
/// Part of the resolution that interacts with the file system.
|
/// Part of the resolution that interacts with the file system.
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
pub trait NpmPackageFsInstaller: Send + Sync {
|
pub trait NpmPackageFsInstaller: std::fmt::Debug + Send + Sync {
|
||||||
async fn cache_packages<'a>(
|
async fn cache_packages<'a>(
|
||||||
&self,
|
&self,
|
||||||
caching: PackageCaching<'a>,
|
caching: PackageCaching<'a>,
|
|
@ -11,14 +11,14 @@ use deno_core::futures::StreamExt;
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
use deno_npm::NpmResolutionPackage;
|
use deno_npm::NpmResolutionPackage;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_resolver::npm::managed::NpmResolution;
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
|
|
||||||
use super::common::lifecycle_scripts::LifecycleScriptsStrategy;
|
use super::common::lifecycle_scripts::LifecycleScriptsStrategy;
|
||||||
use super::common::NpmPackageFsInstaller;
|
use super::common::NpmPackageFsInstaller;
|
||||||
|
use super::PackageCaching;
|
||||||
use crate::args::LifecycleScriptsConfig;
|
use crate::args::LifecycleScriptsConfig;
|
||||||
use crate::cache::FastInsecureHasher;
|
use crate::cache::FastInsecureHasher;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::npm::managed::PackageCaching;
|
|
||||||
use crate::npm::CliNpmCache;
|
use crate::npm::CliNpmCache;
|
||||||
use crate::npm::CliNpmTarballCache;
|
use crate::npm::CliNpmTarballCache;
|
||||||
|
|
||||||
|
@ -27,25 +27,25 @@ use crate::npm::CliNpmTarballCache;
|
||||||
pub struct GlobalNpmPackageInstaller {
|
pub struct GlobalNpmPackageInstaller {
|
||||||
cache: Arc<CliNpmCache>,
|
cache: Arc<CliNpmCache>,
|
||||||
tarball_cache: Arc<CliNpmTarballCache>,
|
tarball_cache: Arc<CliNpmTarballCache>,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolutionCell>,
|
||||||
system_info: NpmSystemInfo,
|
|
||||||
lifecycle_scripts: LifecycleScriptsConfig,
|
lifecycle_scripts: LifecycleScriptsConfig,
|
||||||
|
system_info: NpmSystemInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalNpmPackageInstaller {
|
impl GlobalNpmPackageInstaller {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cache: Arc<CliNpmCache>,
|
cache: Arc<CliNpmCache>,
|
||||||
tarball_cache: Arc<CliNpmTarballCache>,
|
tarball_cache: Arc<CliNpmTarballCache>,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolutionCell>,
|
||||||
system_info: NpmSystemInfo,
|
|
||||||
lifecycle_scripts: LifecycleScriptsConfig,
|
lifecycle_scripts: LifecycleScriptsConfig,
|
||||||
|
system_info: NpmSystemInfo,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cache,
|
cache,
|
||||||
tarball_cache,
|
tarball_cache,
|
||||||
resolution,
|
resolution,
|
||||||
system_info,
|
|
||||||
lifecycle_scripts,
|
lifecycle_scripts,
|
||||||
|
system_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,7 +25,7 @@ use deno_npm::NpmResolutionPackage;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_path_util::fs::atomic_write_file_with_retries;
|
use deno_path_util::fs::atomic_write_file_with_retries;
|
||||||
use deno_resolver::npm::get_package_folder_id_folder_name;
|
use deno_resolver::npm::get_package_folder_id_folder_name;
|
||||||
use deno_resolver::npm::managed::NpmResolution;
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::StackString;
|
use deno_semver::StackString;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -33,11 +33,11 @@ use serde::Serialize;
|
||||||
|
|
||||||
use super::common::bin_entries;
|
use super::common::bin_entries;
|
||||||
use super::common::NpmPackageFsInstaller;
|
use super::common::NpmPackageFsInstaller;
|
||||||
|
use super::PackageCaching;
|
||||||
use crate::args::LifecycleScriptsConfig;
|
use crate::args::LifecycleScriptsConfig;
|
||||||
use crate::args::NpmInstallDepsProvider;
|
use crate::args::NpmInstallDepsProvider;
|
||||||
use crate::cache::CACHE_PERM;
|
use crate::cache::CACHE_PERM;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::npm::managed::PackageCaching;
|
|
||||||
use crate::npm::CliNpmCache;
|
use crate::npm::CliNpmCache;
|
||||||
use crate::npm::CliNpmTarballCache;
|
use crate::npm::CliNpmTarballCache;
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
|
@ -54,12 +54,12 @@ pub struct LocalNpmPackageInstaller {
|
||||||
cache: Arc<CliNpmCache>,
|
cache: Arc<CliNpmCache>,
|
||||||
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolutionCell>,
|
||||||
sys: CliSys,
|
sys: CliSys,
|
||||||
tarball_cache: Arc<CliNpmTarballCache>,
|
tarball_cache: Arc<CliNpmTarballCache>,
|
||||||
|
lifecycle_scripts: LifecycleScriptsConfig,
|
||||||
root_node_modules_path: PathBuf,
|
root_node_modules_path: PathBuf,
|
||||||
system_info: NpmSystemInfo,
|
system_info: NpmSystemInfo,
|
||||||
lifecycle_scripts: LifecycleScriptsConfig,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalNpmPackageInstaller {
|
impl LocalNpmPackageInstaller {
|
||||||
|
@ -68,12 +68,12 @@ impl LocalNpmPackageInstaller {
|
||||||
cache: Arc<CliNpmCache>,
|
cache: Arc<CliNpmCache>,
|
||||||
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolutionCell>,
|
||||||
sys: CliSys,
|
sys: CliSys,
|
||||||
tarball_cache: Arc<CliNpmTarballCache>,
|
tarball_cache: Arc<CliNpmTarballCache>,
|
||||||
node_modules_folder: PathBuf,
|
node_modules_folder: PathBuf,
|
||||||
system_info: NpmSystemInfo,
|
|
||||||
lifecycle_scripts: LifecycleScriptsConfig,
|
lifecycle_scripts: LifecycleScriptsConfig,
|
||||||
|
system_info: NpmSystemInfo,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cache,
|
cache,
|
||||||
|
@ -82,9 +82,9 @@ impl LocalNpmPackageInstaller {
|
||||||
resolution,
|
resolution,
|
||||||
tarball_cache,
|
tarball_cache,
|
||||||
sys,
|
sys,
|
||||||
|
lifecycle_scripts,
|
||||||
root_node_modules_path: node_modules_folder,
|
root_node_modules_path: node_modules_folder,
|
||||||
system_info,
|
system_info,
|
||||||
lifecycle_scripts,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
283
cli/npm/installer/mod.rs
Normal file
283
cli/npm/installer/mod.rs
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::unsync::sync::AtomicFlag;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
use deno_npm::registry::NpmPackageInfo;
|
||||||
|
use deno_npm::registry::NpmRegistryPackageInfoLoadError;
|
||||||
|
use deno_npm::NpmSystemInfo;
|
||||||
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
|
use deno_runtime::colors;
|
||||||
|
use deno_semver::package::PackageReq;
|
||||||
|
|
||||||
|
pub use self::common::NpmPackageFsInstaller;
|
||||||
|
use self::global::GlobalNpmPackageInstaller;
|
||||||
|
use self::local::LocalNpmPackageInstaller;
|
||||||
|
pub use self::resolution::AddPkgReqsResult;
|
||||||
|
pub use self::resolution::NpmResolutionInstaller;
|
||||||
|
use super::NpmResolutionInitializer;
|
||||||
|
use crate::args::CliLockfile;
|
||||||
|
use crate::args::LifecycleScriptsConfig;
|
||||||
|
use crate::args::NpmInstallDepsProvider;
|
||||||
|
use crate::args::PackageJsonDepValueParseWithLocationError;
|
||||||
|
use crate::npm::CliNpmCache;
|
||||||
|
use crate::npm::CliNpmTarballCache;
|
||||||
|
use crate::sys::CliSys;
|
||||||
|
use crate::util::progress_bar::ProgressBar;
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
mod global;
|
||||||
|
mod local;
|
||||||
|
mod resolution;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum PackageCaching<'a> {
|
||||||
|
Only(Cow<'a, [PackageReq]>),
|
||||||
|
All,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NpmInstaller {
|
||||||
|
fs_installer: Arc<dyn NpmPackageFsInstaller>,
|
||||||
|
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
||||||
|
npm_resolution_initializer: Arc<NpmResolutionInitializer>,
|
||||||
|
npm_resolution_installer: Arc<NpmResolutionInstaller>,
|
||||||
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
|
npm_resolution: Arc<NpmResolutionCell>,
|
||||||
|
top_level_install_flag: AtomicFlag,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NpmInstaller {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn new(
|
||||||
|
npm_cache: Arc<CliNpmCache>,
|
||||||
|
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
||||||
|
npm_resolution: Arc<NpmResolutionCell>,
|
||||||
|
npm_resolution_initializer: Arc<NpmResolutionInitializer>,
|
||||||
|
npm_resolution_installer: Arc<NpmResolutionInstaller>,
|
||||||
|
progress_bar: &ProgressBar,
|
||||||
|
sys: CliSys,
|
||||||
|
tarball_cache: Arc<CliNpmTarballCache>,
|
||||||
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
|
maybe_node_modules_path: Option<PathBuf>,
|
||||||
|
lifecycle_scripts: LifecycleScriptsConfig,
|
||||||
|
system_info: NpmSystemInfo,
|
||||||
|
) -> Self {
|
||||||
|
let fs_installer: Arc<dyn NpmPackageFsInstaller> =
|
||||||
|
match maybe_node_modules_path {
|
||||||
|
Some(node_modules_folder) => Arc::new(LocalNpmPackageInstaller::new(
|
||||||
|
npm_cache,
|
||||||
|
npm_install_deps_provider.clone(),
|
||||||
|
progress_bar.clone(),
|
||||||
|
npm_resolution.clone(),
|
||||||
|
sys,
|
||||||
|
tarball_cache,
|
||||||
|
node_modules_folder,
|
||||||
|
lifecycle_scripts,
|
||||||
|
system_info,
|
||||||
|
)),
|
||||||
|
None => Arc::new(GlobalNpmPackageInstaller::new(
|
||||||
|
npm_cache,
|
||||||
|
tarball_cache,
|
||||||
|
npm_resolution.clone(),
|
||||||
|
lifecycle_scripts,
|
||||||
|
system_info,
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
Self {
|
||||||
|
fs_installer,
|
||||||
|
npm_install_deps_provider,
|
||||||
|
npm_resolution,
|
||||||
|
npm_resolution_initializer,
|
||||||
|
npm_resolution_installer,
|
||||||
|
maybe_lockfile,
|
||||||
|
top_level_install_flag: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds package requirements to the resolver and ensures everything is setup.
|
||||||
|
/// This includes setting up the `node_modules` directory, if applicable.
|
||||||
|
pub async fn add_and_cache_package_reqs(
|
||||||
|
&self,
|
||||||
|
packages: &[PackageReq],
|
||||||
|
) -> Result<(), JsErrorBox> {
|
||||||
|
self.npm_resolution_initializer.ensure_initialized().await?;
|
||||||
|
self
|
||||||
|
.add_package_reqs_raw(
|
||||||
|
packages,
|
||||||
|
Some(PackageCaching::Only(packages.into())),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.dependencies_result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_package_reqs_no_cache(
|
||||||
|
&self,
|
||||||
|
packages: &[PackageReq],
|
||||||
|
) -> Result<(), JsErrorBox> {
|
||||||
|
self.npm_resolution_initializer.ensure_initialized().await?;
|
||||||
|
self
|
||||||
|
.add_package_reqs_raw(packages, None)
|
||||||
|
.await
|
||||||
|
.dependencies_result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_package_reqs(
|
||||||
|
&self,
|
||||||
|
packages: &[PackageReq],
|
||||||
|
caching: PackageCaching<'_>,
|
||||||
|
) -> Result<(), JsErrorBox> {
|
||||||
|
self
|
||||||
|
.add_package_reqs_raw(packages, Some(caching))
|
||||||
|
.await
|
||||||
|
.dependencies_result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_package_reqs_raw<'a>(
|
||||||
|
&self,
|
||||||
|
packages: &[PackageReq],
|
||||||
|
caching: Option<PackageCaching<'a>>,
|
||||||
|
) -> AddPkgReqsResult {
|
||||||
|
if packages.is_empty() {
|
||||||
|
return AddPkgReqsResult {
|
||||||
|
dependencies_result: Ok(()),
|
||||||
|
results: vec![],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
self.npm_resolution_initializer.debug_assert_initialized();
|
||||||
|
|
||||||
|
let mut result = self
|
||||||
|
.npm_resolution_installer
|
||||||
|
.add_package_reqs(packages)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if result.dependencies_result.is_ok() {
|
||||||
|
if let Some(lockfile) = self.maybe_lockfile.as_ref() {
|
||||||
|
result.dependencies_result = lockfile.error_if_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if result.dependencies_result.is_ok() {
|
||||||
|
if let Some(caching) = caching {
|
||||||
|
result.dependencies_result = self.cache_packages(caching).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
.npm_resolution_installer
|
||||||
|
.set_package_reqs(packages)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn inject_synthetic_types_node_package(
|
||||||
|
&self,
|
||||||
|
) -> Result<(), JsErrorBox> {
|
||||||
|
self.npm_resolution_initializer.ensure_initialized().await?;
|
||||||
|
let reqs = &[PackageReq::from_str("@types/node").unwrap()];
|
||||||
|
// add and ensure this isn't added to the lockfile
|
||||||
|
self
|
||||||
|
.add_package_reqs(reqs, PackageCaching::Only(reqs.into()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cache_package_info(
|
||||||
|
&self,
|
||||||
|
package_name: &str,
|
||||||
|
) -> Result<Arc<NpmPackageInfo>, NpmRegistryPackageInfoLoadError> {
|
||||||
|
self
|
||||||
|
.npm_resolution_installer
|
||||||
|
.cache_package_info(package_name)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cache_packages(
|
||||||
|
&self,
|
||||||
|
caching: PackageCaching<'_>,
|
||||||
|
) -> Result<(), JsErrorBox> {
|
||||||
|
self.npm_resolution_initializer.ensure_initialized().await?;
|
||||||
|
self.fs_installer.cache_packages(caching).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ensure_no_pkg_json_dep_errors(
|
||||||
|
&self,
|
||||||
|
) -> Result<(), Box<PackageJsonDepValueParseWithLocationError>> {
|
||||||
|
for err in self.npm_install_deps_provider.pkg_json_dep_errors() {
|
||||||
|
match err.source.as_kind() {
|
||||||
|
deno_package_json::PackageJsonDepValueParseErrorKind::VersionReq(_) => {
|
||||||
|
return Err(Box::new(err.clone()));
|
||||||
|
}
|
||||||
|
deno_package_json::PackageJsonDepValueParseErrorKind::Unsupported {
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// only warn for this one
|
||||||
|
log::warn!(
|
||||||
|
"{} {}\n at {}",
|
||||||
|
colors::yellow("Warning"),
|
||||||
|
err.source,
|
||||||
|
err.location,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensures that the top level `package.json` dependencies are installed.
|
||||||
|
/// This may set up the `node_modules` directory.
|
||||||
|
///
|
||||||
|
/// Returns `true` if the top level packages are already installed. A
|
||||||
|
/// return value of `false` means that new packages were added to the NPM resolution.
|
||||||
|
pub async fn ensure_top_level_package_json_install(
|
||||||
|
&self,
|
||||||
|
) -> Result<bool, JsErrorBox> {
|
||||||
|
if !self.top_level_install_flag.raise() {
|
||||||
|
return Ok(true); // already did this
|
||||||
|
}
|
||||||
|
|
||||||
|
self.npm_resolution_initializer.ensure_initialized().await?;
|
||||||
|
|
||||||
|
let pkg_json_remote_pkgs = self.npm_install_deps_provider.remote_pkgs();
|
||||||
|
if pkg_json_remote_pkgs.is_empty() {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if something needs resolving before bothering to load all
|
||||||
|
// the package information (which is slow)
|
||||||
|
if pkg_json_remote_pkgs.iter().all(|pkg| {
|
||||||
|
self
|
||||||
|
.npm_resolution
|
||||||
|
.resolve_pkg_id_from_pkg_req(&pkg.req)
|
||||||
|
.is_ok()
|
||||||
|
}) {
|
||||||
|
log::debug!(
|
||||||
|
"All package.json deps resolvable. Skipping top level install."
|
||||||
|
);
|
||||||
|
return Ok(true); // everything is already resolvable
|
||||||
|
}
|
||||||
|
|
||||||
|
let pkg_reqs = pkg_json_remote_pkgs
|
||||||
|
.iter()
|
||||||
|
.map(|pkg| pkg.req.clone())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
self.add_package_reqs_no_cache(&pkg_reqs).await?;
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,12 +8,14 @@ use deno_core::error::AnyError;
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
use deno_lockfile::NpmPackageDependencyLockfileInfo;
|
use deno_lockfile::NpmPackageDependencyLockfileInfo;
|
||||||
use deno_lockfile::NpmPackageLockfileInfo;
|
use deno_lockfile::NpmPackageLockfileInfo;
|
||||||
|
use deno_npm::registry::NpmPackageInfo;
|
||||||
use deno_npm::registry::NpmRegistryApi;
|
use deno_npm::registry::NpmRegistryApi;
|
||||||
|
use deno_npm::registry::NpmRegistryPackageInfoLoadError;
|
||||||
use deno_npm::resolution::AddPkgReqsOptions;
|
use deno_npm::resolution::AddPkgReqsOptions;
|
||||||
use deno_npm::resolution::NpmResolutionError;
|
use deno_npm::resolution::NpmResolutionError;
|
||||||
use deno_npm::resolution::NpmResolutionSnapshot;
|
use deno_npm::resolution::NpmResolutionSnapshot;
|
||||||
use deno_npm::NpmResolutionPackage;
|
use deno_npm::NpmResolutionPackage;
|
||||||
use deno_resolver::npm::managed::NpmResolution;
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
use deno_semver::jsr::JsrDepPackageReq;
|
use deno_semver::jsr::JsrDepPackageReq;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
@ -35,9 +37,10 @@ pub struct AddPkgReqsResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the npm resolution with the provided package requirements.
|
/// Updates the npm resolution with the provided package requirements.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct NpmResolutionInstaller {
|
pub struct NpmResolutionInstaller {
|
||||||
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolutionCell>,
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
update_queue: TaskQueue,
|
update_queue: TaskQueue,
|
||||||
}
|
}
|
||||||
|
@ -45,7 +48,7 @@ pub struct NpmResolutionInstaller {
|
||||||
impl NpmResolutionInstaller {
|
impl NpmResolutionInstaller {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolutionCell>,
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -56,6 +59,14 @@ impl NpmResolutionInstaller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn cache_package_info(
|
||||||
|
&self,
|
||||||
|
package_name: &str,
|
||||||
|
) -> Result<Arc<NpmPackageInfo>, NpmRegistryPackageInfoLoadError> {
|
||||||
|
// this will internally cache the package information
|
||||||
|
self.registry_info_provider.package_info(package_name).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn add_package_reqs(
|
pub async fn add_package_reqs(
|
||||||
&self,
|
&self,
|
||||||
package_reqs: &[PackageReq],
|
package_reqs: &[PackageReq],
|
496
cli/npm/managed.rs
Normal file
496
cli/npm/managed.rs
Normal file
|
@ -0,0 +1,496 @@
|
||||||
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use deno_ast::ModuleSpecifier;
|
||||||
|
use deno_cache_dir::npm::NpmCacheDir;
|
||||||
|
use deno_core::parking_lot::Mutex;
|
||||||
|
use deno_core::serde_json;
|
||||||
|
use deno_core::url::Url;
|
||||||
|
use deno_error::JsError;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
|
use deno_npm::registry::NpmRegistryApi;
|
||||||
|
use deno_npm::resolution::NpmResolutionSnapshot;
|
||||||
|
use deno_npm::resolution::PackageReqNotFoundError;
|
||||||
|
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
||||||
|
use deno_npm::NpmPackageId;
|
||||||
|
use deno_npm::NpmResolutionPackage;
|
||||||
|
use deno_npm::NpmSystemInfo;
|
||||||
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
|
use deno_resolver::npm::managed::ResolvePkgFolderFromDenoModuleError;
|
||||||
|
use deno_resolver::npm::managed::ResolvePkgFolderFromPkgIdError;
|
||||||
|
use deno_resolver::npm::managed::ResolvePkgIdFromSpecifierError;
|
||||||
|
use deno_resolver::npm::ByonmOrManagedNpmResolver;
|
||||||
|
use deno_resolver::npm::ManagedNpmResolver;
|
||||||
|
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
|
||||||
|
use deno_runtime::ops::process::NpmProcessStateProvider;
|
||||||
|
use deno_semver::package::PackageNv;
|
||||||
|
use deno_semver::package::PackageReq;
|
||||||
|
use node_resolver::NpmPackageFolderResolver;
|
||||||
|
use sys_traits::FsMetadata;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use super::CliNpmRegistryInfoProvider;
|
||||||
|
use super::CliNpmResolver;
|
||||||
|
use super::InnerCliNpmResolverRef;
|
||||||
|
use crate::args::CliLockfile;
|
||||||
|
use crate::args::NpmProcessState;
|
||||||
|
use crate::args::NpmProcessStateKind;
|
||||||
|
use crate::cache::FastInsecureHasher;
|
||||||
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum CliNpmResolverManagedSnapshotOption {
|
||||||
|
ResolveFromLockfile(Arc<CliLockfile>),
|
||||||
|
Specified(Option<ValidSerializedNpmResolutionSnapshot>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum SyncState {
|
||||||
|
Pending(Option<CliNpmResolverManagedSnapshotOption>),
|
||||||
|
Err(ResolveSnapshotError),
|
||||||
|
Success,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NpmResolutionInitializer {
|
||||||
|
npm_registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
||||||
|
npm_resolution: Arc<NpmResolutionCell>,
|
||||||
|
queue: tokio::sync::Mutex<()>,
|
||||||
|
sync_state: Mutex<SyncState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NpmResolutionInitializer {
|
||||||
|
pub fn new(
|
||||||
|
npm_registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
||||||
|
npm_resolution: Arc<NpmResolutionCell>,
|
||||||
|
snapshot_option: CliNpmResolverManagedSnapshotOption,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
npm_registry_info_provider,
|
||||||
|
npm_resolution,
|
||||||
|
queue: tokio::sync::Mutex::new(()),
|
||||||
|
sync_state: Mutex::new(SyncState::Pending(Some(snapshot_option))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
pub fn debug_assert_initialized(&self) {
|
||||||
|
if !matches!(*self.sync_state.lock(), SyncState::Success) {
|
||||||
|
panic!("debug assert: npm resolution must be initialized before calling this code");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn ensure_initialized(&self) -> Result<(), JsErrorBox> {
|
||||||
|
// fast exit if not pending
|
||||||
|
{
|
||||||
|
match &*self.sync_state.lock() {
|
||||||
|
SyncState::Pending(_) => {}
|
||||||
|
SyncState::Err(err) => return Err(JsErrorBox::from_err(err.clone())),
|
||||||
|
SyncState::Success => return Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only allow one task in here at a time
|
||||||
|
let _guard = self.queue.lock().await;
|
||||||
|
|
||||||
|
let snapshot_option = {
|
||||||
|
let mut sync_state = self.sync_state.lock();
|
||||||
|
match &mut *sync_state {
|
||||||
|
SyncState::Pending(snapshot_option) => {
|
||||||
|
// this should never panic, but if it does it means that a
|
||||||
|
// previous future was dropped while initialization occurred...
|
||||||
|
// that should never happen because this is initialized during
|
||||||
|
// startup
|
||||||
|
snapshot_option.take().unwrap()
|
||||||
|
}
|
||||||
|
// another thread updated the state while we were waiting
|
||||||
|
SyncState::Err(resolve_snapshot_error) => {
|
||||||
|
return Err(JsErrorBox::from_err(resolve_snapshot_error.clone()));
|
||||||
|
}
|
||||||
|
SyncState::Success => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match resolve_snapshot(&self.npm_registry_info_provider, snapshot_option)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(maybe_snapshot) => {
|
||||||
|
if let Some(snapshot) = maybe_snapshot {
|
||||||
|
self
|
||||||
|
.npm_resolution
|
||||||
|
.set_snapshot(NpmResolutionSnapshot::new(snapshot));
|
||||||
|
}
|
||||||
|
let mut sync_state = self.sync_state.lock();
|
||||||
|
*sync_state = SyncState::Success;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let mut sync_state = self.sync_state.lock();
|
||||||
|
*sync_state = SyncState::Err(err.clone());
|
||||||
|
Err(JsErrorBox::from_err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CliManagedNpmResolverCreateOptions {
|
||||||
|
pub npm_cache_dir: Arc<NpmCacheDir>,
|
||||||
|
pub sys: CliSys,
|
||||||
|
pub maybe_node_modules_path: Option<PathBuf>,
|
||||||
|
pub npm_system_info: NpmSystemInfo,
|
||||||
|
pub npmrc: Arc<ResolvedNpmRc>,
|
||||||
|
pub npm_resolution: Arc<NpmResolutionCell>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_managed_npm_resolver(
|
||||||
|
options: CliManagedNpmResolverCreateOptions,
|
||||||
|
) -> Arc<dyn CliNpmResolver> {
|
||||||
|
let managed_npm_resolver =
|
||||||
|
Arc::new(ManagedNpmResolver::<CliSys>::new::<CliSys>(
|
||||||
|
&options.npm_cache_dir,
|
||||||
|
&options.npmrc,
|
||||||
|
options.npm_resolution.clone(),
|
||||||
|
options.sys.clone(),
|
||||||
|
options.maybe_node_modules_path,
|
||||||
|
));
|
||||||
|
Arc::new(ManagedCliNpmResolver::new(
|
||||||
|
managed_npm_resolver,
|
||||||
|
options.npm_cache_dir,
|
||||||
|
options.npmrc,
|
||||||
|
options.npm_resolution,
|
||||||
|
options.sys,
|
||||||
|
options.npm_system_info,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error, Clone, JsError)]
|
||||||
|
#[error("failed reading lockfile '{}'", lockfile_path.display())]
|
||||||
|
#[class(inherit)]
|
||||||
|
pub struct ResolveSnapshotError {
|
||||||
|
lockfile_path: PathBuf,
|
||||||
|
#[inherit]
|
||||||
|
#[source]
|
||||||
|
source: SnapshotFromLockfileError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResolveSnapshotError {
|
||||||
|
pub fn maybe_integrity_check_error(
|
||||||
|
&self,
|
||||||
|
) -> Option<&deno_npm::resolution::IntegrityCheckFailedError> {
|
||||||
|
match &self.source {
|
||||||
|
SnapshotFromLockfileError::SnapshotFromLockfile(
|
||||||
|
deno_npm::resolution::SnapshotFromLockfileError::IntegrityCheckFailed(
|
||||||
|
err,
|
||||||
|
),
|
||||||
|
) => Some(err),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn resolve_snapshot(
|
||||||
|
registry_info_provider: &Arc<CliNpmRegistryInfoProvider>,
|
||||||
|
snapshot: CliNpmResolverManagedSnapshotOption,
|
||||||
|
) -> Result<Option<ValidSerializedNpmResolutionSnapshot>, ResolveSnapshotError>
|
||||||
|
{
|
||||||
|
match snapshot {
|
||||||
|
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(lockfile) => {
|
||||||
|
if !lockfile.overwrite() {
|
||||||
|
let snapshot = snapshot_from_lockfile(
|
||||||
|
lockfile.clone(),
|
||||||
|
®istry_info_provider.as_npm_registry_api(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|source| ResolveSnapshotError {
|
||||||
|
lockfile_path: lockfile.filename.clone(),
|
||||||
|
source,
|
||||||
|
})?;
|
||||||
|
Ok(Some(snapshot))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CliNpmResolverManagedSnapshotOption::Specified(snapshot) => Ok(snapshot),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error, Clone, JsError)]
|
||||||
|
pub enum SnapshotFromLockfileError {
|
||||||
|
#[error(transparent)]
|
||||||
|
#[class(inherit)]
|
||||||
|
IncompleteError(
|
||||||
|
#[from] deno_npm::resolution::IncompleteSnapshotFromLockfileError,
|
||||||
|
),
|
||||||
|
#[error(transparent)]
|
||||||
|
#[class(inherit)]
|
||||||
|
SnapshotFromLockfile(#[from] deno_npm::resolution::SnapshotFromLockfileError),
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn snapshot_from_lockfile(
|
||||||
|
lockfile: Arc<CliLockfile>,
|
||||||
|
api: &dyn NpmRegistryApi,
|
||||||
|
) -> Result<ValidSerializedNpmResolutionSnapshot, SnapshotFromLockfileError> {
|
||||||
|
let (incomplete_snapshot, skip_integrity_check) = {
|
||||||
|
let lock = lockfile.lock();
|
||||||
|
(
|
||||||
|
deno_npm::resolution::incomplete_snapshot_from_lockfile(&lock)?,
|
||||||
|
lock.overwrite,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let snapshot = deno_npm::resolution::snapshot_from_lockfile(
|
||||||
|
deno_npm::resolution::SnapshotFromLockfileParams {
|
||||||
|
incomplete_snapshot,
|
||||||
|
api,
|
||||||
|
skip_integrity_check,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(snapshot)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 {
|
||||||
|
managed_npm_resolver: Arc<ManagedNpmResolver<CliSys>>,
|
||||||
|
npm_cache_dir: Arc<NpmCacheDir>,
|
||||||
|
npm_rc: Arc<ResolvedNpmRc>,
|
||||||
|
sys: CliSys,
|
||||||
|
resolution: Arc<NpmResolutionCell>,
|
||||||
|
system_info: NpmSystemInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for ManagedCliNpmResolver {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("ManagedCliNpmResolver")
|
||||||
|
.field("<omitted>", &"<omitted>")
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ManagedCliNpmResolver {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn new(
|
||||||
|
managed_npm_resolver: Arc<ManagedNpmResolver<CliSys>>,
|
||||||
|
npm_cache_dir: Arc<NpmCacheDir>,
|
||||||
|
npm_rc: Arc<ResolvedNpmRc>,
|
||||||
|
resolution: Arc<NpmResolutionCell>,
|
||||||
|
sys: CliSys,
|
||||||
|
system_info: NpmSystemInfo,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
managed_npm_resolver,
|
||||||
|
npm_cache_dir,
|
||||||
|
npm_rc,
|
||||||
|
resolution,
|
||||||
|
sys,
|
||||||
|
system_info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_pkg_folder_from_pkg_id(
|
||||||
|
&self,
|
||||||
|
pkg_id: &NpmPackageId,
|
||||||
|
) -> Result<PathBuf, ResolvePkgFolderFromPkgIdError> {
|
||||||
|
self
|
||||||
|
.managed_npm_resolver
|
||||||
|
.resolve_pkg_folder_from_pkg_id(pkg_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolves the package id from the provided specifier.
|
||||||
|
pub fn resolve_pkg_id_from_specifier(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Result<Option<NpmPackageId>, ResolvePkgIdFromSpecifierError> {
|
||||||
|
self
|
||||||
|
.managed_npm_resolver
|
||||||
|
.resolve_pkg_id_from_specifier(specifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_pkg_reqs_from_pkg_id(
|
||||||
|
&self,
|
||||||
|
id: &NpmPackageId,
|
||||||
|
) -> Vec<PackageReq> {
|
||||||
|
self.resolution.resolve_pkg_reqs_from_pkg_id(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_system_packages(
|
||||||
|
&self,
|
||||||
|
system_info: &NpmSystemInfo,
|
||||||
|
) -> Vec<NpmResolutionPackage> {
|
||||||
|
self.resolution.all_system_packages(system_info)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the provided package req's folder is cached.
|
||||||
|
pub fn is_pkg_req_folder_cached(&self, req: &PackageReq) -> bool {
|
||||||
|
self
|
||||||
|
.resolve_pkg_id_from_pkg_req(req)
|
||||||
|
.ok()
|
||||||
|
.and_then(|id| {
|
||||||
|
self
|
||||||
|
.managed_npm_resolver
|
||||||
|
.resolve_pkg_folder_from_pkg_id(&id)
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
|
.map(|folder| self.sys.fs_exists_no_err(folder))
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn snapshot(&self) -> NpmResolutionSnapshot {
|
||||||
|
self.resolution.snapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn top_package_req_for_name(&self, name: &str) -> Option<PackageReq> {
|
||||||
|
let package_reqs = self.resolution.package_reqs();
|
||||||
|
let mut entries = package_reqs
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, nv)| nv.name == name)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
entries.sort_by_key(|(_, nv)| &nv.version);
|
||||||
|
Some(entries.last()?.0.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serialized_valid_snapshot_for_system(
|
||||||
|
&self,
|
||||||
|
system_info: &NpmSystemInfo,
|
||||||
|
) -> ValidSerializedNpmResolutionSnapshot {
|
||||||
|
self
|
||||||
|
.resolution
|
||||||
|
.serialized_valid_snapshot_for_system(system_info)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_pkg_folder_from_deno_module(
|
||||||
|
&self,
|
||||||
|
nv: &PackageNv,
|
||||||
|
) -> Result<PathBuf, ResolvePkgFolderFromDenoModuleError> {
|
||||||
|
self
|
||||||
|
.managed_npm_resolver
|
||||||
|
.resolve_pkg_folder_from_deno_module(nv)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_pkg_id_from_pkg_req(
|
||||||
|
&self,
|
||||||
|
req: &PackageReq,
|
||||||
|
) -> Result<NpmPackageId, PackageReqNotFoundError> {
|
||||||
|
self.resolution.resolve_pkg_id_from_pkg_req(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn maybe_node_modules_path(&self) -> Option<&Path> {
|
||||||
|
self.managed_npm_resolver.node_modules_path()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn global_cache_root_path(&self) -> &Path {
|
||||||
|
self.npm_cache_dir.root_dir()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn global_cache_root_url(&self) -> &Url {
|
||||||
|
self.npm_cache_dir.root_dir_url()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_process_state(
|
||||||
|
snapshot: ValidSerializedNpmResolutionSnapshot,
|
||||||
|
node_modules_path: Option<&Path>,
|
||||||
|
) -> String {
|
||||||
|
serde_json::to_string(&NpmProcessState {
|
||||||
|
kind: NpmProcessStateKind::Snapshot(snapshot.into_serialized()),
|
||||||
|
local_node_modules_path: node_modules_path
|
||||||
|
.map(|p| p.to_string_lossy().to_string()),
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NpmProcessStateProvider for ManagedCliNpmResolver {
|
||||||
|
fn get_npm_process_state(&self) -> String {
|
||||||
|
npm_process_state(
|
||||||
|
self.resolution.serialized_valid_snapshot(),
|
||||||
|
self.managed_npm_resolver.node_modules_path(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CliNpmResolver for ManagedCliNpmResolver {
|
||||||
|
fn into_npm_pkg_folder_resolver(
|
||||||
|
self: Arc<Self>,
|
||||||
|
) -> Arc<dyn NpmPackageFolderResolver> {
|
||||||
|
self.managed_npm_resolver.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_process_state_provider(
|
||||||
|
self: Arc<Self>,
|
||||||
|
) -> Arc<dyn NpmProcessStateProvider> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_byonm_or_managed(
|
||||||
|
self: Arc<Self>,
|
||||||
|
) -> ByonmOrManagedNpmResolver<CliSys> {
|
||||||
|
ByonmOrManagedNpmResolver::Managed(self.managed_npm_resolver.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver> {
|
||||||
|
// create a new snapshotted npm resolution and resolver
|
||||||
|
let npm_resolution =
|
||||||
|
Arc::new(NpmResolutionCell::new(self.resolution.snapshot()));
|
||||||
|
|
||||||
|
Arc::new(ManagedCliNpmResolver::new(
|
||||||
|
Arc::new(ManagedNpmResolver::<CliSys>::new::<CliSys>(
|
||||||
|
&self.npm_cache_dir,
|
||||||
|
&self.npm_rc,
|
||||||
|
npm_resolution.clone(),
|
||||||
|
self.sys.clone(),
|
||||||
|
self.root_node_modules_path().map(ToOwned::to_owned),
|
||||||
|
)),
|
||||||
|
self.npm_cache_dir.clone(),
|
||||||
|
self.npm_rc.clone(),
|
||||||
|
npm_resolution,
|
||||||
|
self.sys.clone(),
|
||||||
|
self.system_info.clone(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_inner(&self) -> InnerCliNpmResolverRef {
|
||||||
|
InnerCliNpmResolverRef::Managed(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_node_modules_path(&self) -> Option<&Path> {
|
||||||
|
self.managed_npm_resolver.node_modules_path()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_state_hash(&self) -> Option<u64> {
|
||||||
|
// We could go further and check all the individual
|
||||||
|
// npm packages, but that's probably overkill.
|
||||||
|
let mut package_reqs = self
|
||||||
|
.resolution
|
||||||
|
.package_reqs()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
package_reqs.sort_by(|a, b| a.0.cmp(&b.0)); // determinism
|
||||||
|
let mut hasher = FastInsecureHasher::new_without_deno_version();
|
||||||
|
// ensure the cache gets busted when turning nodeModulesDir on or off
|
||||||
|
// as this could cause changes in resolution
|
||||||
|
hasher
|
||||||
|
.write_hashable(self.managed_npm_resolver.node_modules_path().is_some());
|
||||||
|
for (pkg_req, pkg_nv) in package_reqs {
|
||||||
|
hasher.write_hashable(&pkg_req);
|
||||||
|
hasher.write_hashable(&pkg_nv);
|
||||||
|
}
|
||||||
|
Some(hasher.finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_pkg_folder_from_deno_module_req(
|
||||||
|
&self,
|
||||||
|
req: &PackageReq,
|
||||||
|
referrer: &Url,
|
||||||
|
) -> Result<PathBuf, ResolvePkgFolderFromDenoReqError> {
|
||||||
|
self
|
||||||
|
.managed_npm_resolver
|
||||||
|
.resolve_pkg_folder_from_deno_module_req(req, referrer)
|
||||||
|
.map_err(ResolvePkgFolderFromDenoReqError::Managed)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,55 +0,0 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use deno_npm::NpmSystemInfo;
|
|
||||||
use deno_resolver::npm::managed::NpmResolution;
|
|
||||||
|
|
||||||
pub use self::common::NpmPackageFsInstaller;
|
|
||||||
use self::global::GlobalNpmPackageInstaller;
|
|
||||||
use self::local::LocalNpmPackageInstaller;
|
|
||||||
use crate::args::LifecycleScriptsConfig;
|
|
||||||
use crate::args::NpmInstallDepsProvider;
|
|
||||||
use crate::npm::CliNpmCache;
|
|
||||||
use crate::npm::CliNpmTarballCache;
|
|
||||||
use crate::sys::CliSys;
|
|
||||||
use crate::util::progress_bar::ProgressBar;
|
|
||||||
|
|
||||||
mod common;
|
|
||||||
mod global;
|
|
||||||
mod local;
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn create_npm_fs_installer(
|
|
||||||
npm_cache: Arc<CliNpmCache>,
|
|
||||||
npm_install_deps_provider: &Arc<NpmInstallDepsProvider>,
|
|
||||||
progress_bar: &ProgressBar,
|
|
||||||
resolution: Arc<NpmResolution>,
|
|
||||||
sys: CliSys,
|
|
||||||
tarball_cache: Arc<CliNpmTarballCache>,
|
|
||||||
maybe_node_modules_path: Option<PathBuf>,
|
|
||||||
system_info: NpmSystemInfo,
|
|
||||||
lifecycle_scripts: LifecycleScriptsConfig,
|
|
||||||
) -> Arc<dyn NpmPackageFsInstaller> {
|
|
||||||
match maybe_node_modules_path {
|
|
||||||
Some(node_modules_folder) => Arc::new(LocalNpmPackageInstaller::new(
|
|
||||||
npm_cache,
|
|
||||||
npm_install_deps_provider.clone(),
|
|
||||||
progress_bar.clone(),
|
|
||||||
resolution,
|
|
||||||
sys,
|
|
||||||
tarball_cache,
|
|
||||||
node_modules_folder,
|
|
||||||
system_info,
|
|
||||||
lifecycle_scripts,
|
|
||||||
)),
|
|
||||||
None => Arc::new(GlobalNpmPackageInstaller::new(
|
|
||||||
npm_cache,
|
|
||||||
tarball_cache,
|
|
||||||
resolution,
|
|
||||||
system_info,
|
|
||||||
lifecycle_scripts,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,768 +0,0 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use deno_ast::ModuleSpecifier;
|
|
||||||
use deno_cache_dir::npm::NpmCacheDir;
|
|
||||||
use deno_core::anyhow::Context;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::serde_json;
|
|
||||||
use deno_core::url::Url;
|
|
||||||
use deno_error::JsErrorBox;
|
|
||||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
|
||||||
use deno_npm::registry::NpmPackageInfo;
|
|
||||||
use deno_npm::registry::NpmRegistryApi;
|
|
||||||
use deno_npm::resolution::NpmResolutionSnapshot;
|
|
||||||
use deno_npm::resolution::PackageReqNotFoundError;
|
|
||||||
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
|
||||||
use deno_npm::NpmPackageId;
|
|
||||||
use deno_npm::NpmResolutionPackage;
|
|
||||||
use deno_npm::NpmSystemInfo;
|
|
||||||
use deno_npm_cache::NpmCacheSetting;
|
|
||||||
use deno_resolver::npm::managed::NpmResolution;
|
|
||||||
use deno_resolver::npm::managed::ResolvePkgFolderFromPkgIdError;
|
|
||||||
use deno_resolver::npm::ByonmOrManagedNpmResolver;
|
|
||||||
use deno_resolver::npm::ManagedNpmResolver;
|
|
||||||
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
|
|
||||||
use deno_runtime::colors;
|
|
||||||
use deno_runtime::ops::process::NpmProcessStateProvider;
|
|
||||||
use deno_semver::package::PackageNv;
|
|
||||||
use deno_semver::package::PackageReq;
|
|
||||||
use installer::AddPkgReqsResult;
|
|
||||||
use installer::NpmResolutionInstaller;
|
|
||||||
use installers::create_npm_fs_installer;
|
|
||||||
use installers::NpmPackageFsInstaller;
|
|
||||||
use node_resolver::NpmPackageFolderResolver;
|
|
||||||
|
|
||||||
use super::CliNpmCache;
|
|
||||||
use super::CliNpmCacheHttpClient;
|
|
||||||
use super::CliNpmRegistryInfoProvider;
|
|
||||||
use super::CliNpmResolver;
|
|
||||||
use super::CliNpmTarballCache;
|
|
||||||
use super::InnerCliNpmResolverRef;
|
|
||||||
use crate::args::CliLockfile;
|
|
||||||
use crate::args::LifecycleScriptsConfig;
|
|
||||||
use crate::args::NpmInstallDepsProvider;
|
|
||||||
use crate::args::NpmProcessState;
|
|
||||||
use crate::args::NpmProcessStateKind;
|
|
||||||
use crate::args::PackageJsonDepValueParseWithLocationError;
|
|
||||||
use crate::cache::FastInsecureHasher;
|
|
||||||
use crate::sys::CliSys;
|
|
||||||
use crate::util::progress_bar::ProgressBar;
|
|
||||||
use crate::util::sync::AtomicFlag;
|
|
||||||
|
|
||||||
mod installer;
|
|
||||||
mod installers;
|
|
||||||
|
|
||||||
pub enum CliNpmResolverManagedSnapshotOption {
|
|
||||||
ResolveFromLockfile(Arc<CliLockfile>),
|
|
||||||
Specified(Option<ValidSerializedNpmResolutionSnapshot>),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CliManagedNpmResolverCreateOptions {
|
|
||||||
pub snapshot: CliNpmResolverManagedSnapshotOption,
|
|
||||||
pub maybe_lockfile: Option<Arc<CliLockfile>>,
|
|
||||||
pub http_client_provider: Arc<crate::http_util::HttpClientProvider>,
|
|
||||||
pub npm_cache_dir: Arc<NpmCacheDir>,
|
|
||||||
pub sys: CliSys,
|
|
||||||
pub cache_setting: deno_cache_dir::file_fetcher::CacheSetting,
|
|
||||||
pub text_only_progress_bar: crate::util::progress_bar::ProgressBar,
|
|
||||||
pub maybe_node_modules_path: Option<PathBuf>,
|
|
||||||
pub npm_system_info: NpmSystemInfo,
|
|
||||||
pub npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
|
||||||
pub npmrc: Arc<ResolvedNpmRc>,
|
|
||||||
pub lifecycle_scripts: LifecycleScriptsConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create_managed_npm_resolver_for_lsp(
|
|
||||||
options: CliManagedNpmResolverCreateOptions,
|
|
||||||
) -> Arc<dyn CliNpmResolver> {
|
|
||||||
let npm_cache = create_cache(&options);
|
|
||||||
let http_client = Arc::new(CliNpmCacheHttpClient::new(
|
|
||||||
options.http_client_provider.clone(),
|
|
||||||
options.text_only_progress_bar.clone(),
|
|
||||||
));
|
|
||||||
let npm_api = create_api(npm_cache.clone(), http_client.clone(), &options);
|
|
||||||
// spawn due to the lsp's `Send` requirement
|
|
||||||
deno_core::unsync::spawn(async move {
|
|
||||||
let snapshot = match resolve_snapshot(&npm_api, options.snapshot).await {
|
|
||||||
Ok(snapshot) => snapshot,
|
|
||||||
Err(err) => {
|
|
||||||
log::warn!("failed to resolve snapshot: {}", err);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
create_inner(
|
|
||||||
http_client,
|
|
||||||
npm_cache,
|
|
||||||
options.npm_cache_dir,
|
|
||||||
options.npm_install_deps_provider,
|
|
||||||
npm_api,
|
|
||||||
options.sys,
|
|
||||||
options.text_only_progress_bar,
|
|
||||||
options.maybe_lockfile,
|
|
||||||
options.npmrc,
|
|
||||||
options.maybe_node_modules_path,
|
|
||||||
options.npm_system_info,
|
|
||||||
snapshot,
|
|
||||||
options.lifecycle_scripts,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create_managed_npm_resolver(
|
|
||||||
options: CliManagedNpmResolverCreateOptions,
|
|
||||||
) -> Result<Arc<dyn CliNpmResolver>, AnyError> {
|
|
||||||
let npm_cache = create_cache(&options);
|
|
||||||
let http_client = Arc::new(CliNpmCacheHttpClient::new(
|
|
||||||
options.http_client_provider.clone(),
|
|
||||||
options.text_only_progress_bar.clone(),
|
|
||||||
));
|
|
||||||
let api = create_api(npm_cache.clone(), http_client.clone(), &options);
|
|
||||||
let snapshot = resolve_snapshot(&api, options.snapshot).await?;
|
|
||||||
Ok(create_inner(
|
|
||||||
http_client,
|
|
||||||
npm_cache,
|
|
||||||
options.npm_cache_dir,
|
|
||||||
options.npm_install_deps_provider,
|
|
||||||
api,
|
|
||||||
options.sys,
|
|
||||||
options.text_only_progress_bar,
|
|
||||||
options.maybe_lockfile,
|
|
||||||
options.npmrc,
|
|
||||||
options.maybe_node_modules_path,
|
|
||||||
options.npm_system_info,
|
|
||||||
snapshot,
|
|
||||||
options.lifecycle_scripts,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
fn create_inner(
|
|
||||||
http_client: Arc<CliNpmCacheHttpClient>,
|
|
||||||
npm_cache: Arc<CliNpmCache>,
|
|
||||||
npm_cache_dir: Arc<NpmCacheDir>,
|
|
||||||
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
|
||||||
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
|
||||||
sys: CliSys,
|
|
||||||
text_only_progress_bar: crate::util::progress_bar::ProgressBar,
|
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
|
||||||
npm_rc: Arc<ResolvedNpmRc>,
|
|
||||||
node_modules_dir_path: Option<PathBuf>,
|
|
||||||
npm_system_info: NpmSystemInfo,
|
|
||||||
snapshot: Option<ValidSerializedNpmResolutionSnapshot>,
|
|
||||||
lifecycle_scripts: LifecycleScriptsConfig,
|
|
||||||
) -> Arc<dyn CliNpmResolver> {
|
|
||||||
let resolution = Arc::new(NpmResolution::from_serialized(snapshot));
|
|
||||||
let tarball_cache = Arc::new(CliNpmTarballCache::new(
|
|
||||||
npm_cache.clone(),
|
|
||||||
http_client,
|
|
||||||
sys.clone(),
|
|
||||||
npm_rc.clone(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let fs_installer = create_npm_fs_installer(
|
|
||||||
npm_cache.clone(),
|
|
||||||
&npm_install_deps_provider,
|
|
||||||
&text_only_progress_bar,
|
|
||||||
resolution.clone(),
|
|
||||||
sys.clone(),
|
|
||||||
tarball_cache.clone(),
|
|
||||||
node_modules_dir_path.clone(),
|
|
||||||
npm_system_info.clone(),
|
|
||||||
lifecycle_scripts.clone(),
|
|
||||||
);
|
|
||||||
let managed_npm_resolver =
|
|
||||||
Arc::new(ManagedNpmResolver::<CliSys>::new::<CliSys>(
|
|
||||||
&npm_cache_dir,
|
|
||||||
&npm_rc,
|
|
||||||
resolution.clone(),
|
|
||||||
sys.clone(),
|
|
||||||
node_modules_dir_path,
|
|
||||||
));
|
|
||||||
Arc::new(ManagedCliNpmResolver::new(
|
|
||||||
fs_installer,
|
|
||||||
maybe_lockfile,
|
|
||||||
managed_npm_resolver,
|
|
||||||
npm_cache,
|
|
||||||
npm_cache_dir,
|
|
||||||
npm_install_deps_provider,
|
|
||||||
npm_rc,
|
|
||||||
registry_info_provider,
|
|
||||||
resolution,
|
|
||||||
sys,
|
|
||||||
tarball_cache,
|
|
||||||
text_only_progress_bar,
|
|
||||||
npm_system_info,
|
|
||||||
lifecycle_scripts,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_cache(
|
|
||||||
options: &CliManagedNpmResolverCreateOptions,
|
|
||||||
) -> Arc<CliNpmCache> {
|
|
||||||
Arc::new(CliNpmCache::new(
|
|
||||||
options.npm_cache_dir.clone(),
|
|
||||||
options.sys.clone(),
|
|
||||||
NpmCacheSetting::from_cache_setting(&options.cache_setting),
|
|
||||||
options.npmrc.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_api(
|
|
||||||
cache: Arc<CliNpmCache>,
|
|
||||||
http_client: Arc<CliNpmCacheHttpClient>,
|
|
||||||
options: &CliManagedNpmResolverCreateOptions,
|
|
||||||
) -> Arc<CliNpmRegistryInfoProvider> {
|
|
||||||
Arc::new(CliNpmRegistryInfoProvider::new(
|
|
||||||
cache,
|
|
||||||
http_client,
|
|
||||||
options.npmrc.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn resolve_snapshot(
|
|
||||||
registry_info_provider: &Arc<CliNpmRegistryInfoProvider>,
|
|
||||||
snapshot: CliNpmResolverManagedSnapshotOption,
|
|
||||||
) -> Result<Option<ValidSerializedNpmResolutionSnapshot>, AnyError> {
|
|
||||||
match snapshot {
|
|
||||||
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(lockfile) => {
|
|
||||||
if !lockfile.overwrite() {
|
|
||||||
let snapshot = snapshot_from_lockfile(
|
|
||||||
lockfile.clone(),
|
|
||||||
®istry_info_provider.as_npm_registry_api(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.with_context(|| {
|
|
||||||
format!("failed reading lockfile '{}'", lockfile.filename.display())
|
|
||||||
})?;
|
|
||||||
Ok(Some(snapshot))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CliNpmResolverManagedSnapshotOption::Specified(snapshot) => Ok(snapshot),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn snapshot_from_lockfile(
|
|
||||||
lockfile: Arc<CliLockfile>,
|
|
||||||
api: &dyn NpmRegistryApi,
|
|
||||||
) -> Result<ValidSerializedNpmResolutionSnapshot, AnyError> {
|
|
||||||
let (incomplete_snapshot, skip_integrity_check) = {
|
|
||||||
let lock = lockfile.lock();
|
|
||||||
(
|
|
||||||
deno_npm::resolution::incomplete_snapshot_from_lockfile(&lock)?,
|
|
||||||
lock.overwrite,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let snapshot = deno_npm::resolution::snapshot_from_lockfile(
|
|
||||||
deno_npm::resolution::SnapshotFromLockfileParams {
|
|
||||||
incomplete_snapshot,
|
|
||||||
api,
|
|
||||||
skip_integrity_check,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(snapshot)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub enum PackageCaching<'a> {
|
|
||||||
Only(Cow<'a, [PackageReq]>),
|
|
||||||
All,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
|
||||||
pub enum ResolvePkgFolderFromDenoModuleError {
|
|
||||||
#[class(inherit)]
|
|
||||||
#[error(transparent)]
|
|
||||||
PackageNvNotFound(#[from] deno_npm::resolution::PackageNvNotFoundError),
|
|
||||||
#[class(inherit)]
|
|
||||||
#[error(transparent)]
|
|
||||||
ResolvePkgFolderFromPkgId(#[from] ResolvePkgFolderFromPkgIdError),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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_installer: Arc<dyn NpmPackageFsInstaller>,
|
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
|
||||||
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
|
||||||
managed_npm_resolver: Arc<ManagedNpmResolver<CliSys>>,
|
|
||||||
npm_cache: Arc<CliNpmCache>,
|
|
||||||
npm_cache_dir: Arc<NpmCacheDir>,
|
|
||||||
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
|
||||||
npm_rc: Arc<ResolvedNpmRc>,
|
|
||||||
sys: CliSys,
|
|
||||||
resolution: Arc<NpmResolution>,
|
|
||||||
resolution_installer: NpmResolutionInstaller,
|
|
||||||
tarball_cache: Arc<CliNpmTarballCache>,
|
|
||||||
text_only_progress_bar: ProgressBar,
|
|
||||||
npm_system_info: NpmSystemInfo,
|
|
||||||
top_level_install_flag: AtomicFlag,
|
|
||||||
lifecycle_scripts: LifecycleScriptsConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for ManagedCliNpmResolver {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("ManagedCliNpmResolver")
|
|
||||||
.field("<omitted>", &"<omitted>")
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ManagedCliNpmResolver {
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn new(
|
|
||||||
fs_installer: Arc<dyn NpmPackageFsInstaller>,
|
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
|
||||||
managed_npm_resolver: Arc<ManagedNpmResolver<CliSys>>,
|
|
||||||
npm_cache: Arc<CliNpmCache>,
|
|
||||||
npm_cache_dir: Arc<NpmCacheDir>,
|
|
||||||
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
|
|
||||||
npm_rc: Arc<ResolvedNpmRc>,
|
|
||||||
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
|
|
||||||
resolution: Arc<NpmResolution>,
|
|
||||||
sys: CliSys,
|
|
||||||
tarball_cache: Arc<CliNpmTarballCache>,
|
|
||||||
text_only_progress_bar: ProgressBar,
|
|
||||||
npm_system_info: NpmSystemInfo,
|
|
||||||
lifecycle_scripts: LifecycleScriptsConfig,
|
|
||||||
) -> Self {
|
|
||||||
let resolution_installer = NpmResolutionInstaller::new(
|
|
||||||
registry_info_provider.clone(),
|
|
||||||
resolution.clone(),
|
|
||||||
maybe_lockfile.clone(),
|
|
||||||
);
|
|
||||||
Self {
|
|
||||||
fs_installer,
|
|
||||||
maybe_lockfile,
|
|
||||||
managed_npm_resolver,
|
|
||||||
npm_cache,
|
|
||||||
npm_cache_dir,
|
|
||||||
npm_install_deps_provider,
|
|
||||||
npm_rc,
|
|
||||||
registry_info_provider,
|
|
||||||
text_only_progress_bar,
|
|
||||||
resolution,
|
|
||||||
resolution_installer,
|
|
||||||
sys,
|
|
||||||
tarball_cache,
|
|
||||||
npm_system_info,
|
|
||||||
top_level_install_flag: Default::default(),
|
|
||||||
lifecycle_scripts,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_pkg_folder_from_pkg_id(
|
|
||||||
&self,
|
|
||||||
pkg_id: &NpmPackageId,
|
|
||||||
) -> Result<PathBuf, ResolvePkgFolderFromPkgIdError> {
|
|
||||||
self
|
|
||||||
.managed_npm_resolver
|
|
||||||
.resolve_pkg_folder_from_pkg_id(pkg_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resolves the package id from the provided specifier.
|
|
||||||
pub fn resolve_pkg_id_from_specifier(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
) -> Result<Option<NpmPackageId>, AnyError> {
|
|
||||||
let Some(cache_folder_id) = self
|
|
||||||
.managed_npm_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)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_pkg_reqs_from_pkg_id(
|
|
||||||
&self,
|
|
||||||
id: &NpmPackageId,
|
|
||||||
) -> Vec<PackageReq> {
|
|
||||||
self.resolution.resolve_pkg_reqs_from_pkg_id(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempts to get the package size in bytes.
|
|
||||||
pub fn package_size(
|
|
||||||
&self,
|
|
||||||
package_id: &NpmPackageId,
|
|
||||||
) -> Result<u64, AnyError> {
|
|
||||||
let package_folder = self
|
|
||||||
.managed_npm_resolver
|
|
||||||
.resolve_pkg_folder_from_pkg_id(package_id)?;
|
|
||||||
Ok(crate::util::fs::dir_size(&package_folder)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn all_system_packages(
|
|
||||||
&self,
|
|
||||||
system_info: &NpmSystemInfo,
|
|
||||||
) -> Vec<NpmResolutionPackage> {
|
|
||||||
self.resolution.all_system_packages(system_info)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if the provided package req's folder is cached.
|
|
||||||
pub fn is_pkg_req_folder_cached(&self, req: &PackageReq) -> bool {
|
|
||||||
self
|
|
||||||
.resolve_pkg_id_from_pkg_req(req)
|
|
||||||
.ok()
|
|
||||||
.and_then(|id| {
|
|
||||||
self
|
|
||||||
.managed_npm_resolver
|
|
||||||
.resolve_pkg_folder_from_pkg_id(&id)
|
|
||||||
.ok()
|
|
||||||
})
|
|
||||||
.map(|folder| folder.exists())
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds package requirements to the resolver and ensures everything is setup.
|
|
||||||
/// This includes setting up the `node_modules` directory, if applicable.
|
|
||||||
pub async fn add_and_cache_package_reqs(
|
|
||||||
&self,
|
|
||||||
packages: &[PackageReq],
|
|
||||||
) -> Result<(), JsErrorBox> {
|
|
||||||
self
|
|
||||||
.add_package_reqs_raw(
|
|
||||||
packages,
|
|
||||||
Some(PackageCaching::Only(packages.into())),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.dependencies_result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn add_package_reqs_no_cache(
|
|
||||||
&self,
|
|
||||||
packages: &[PackageReq],
|
|
||||||
) -> Result<(), JsErrorBox> {
|
|
||||||
self
|
|
||||||
.add_package_reqs_raw(packages, None)
|
|
||||||
.await
|
|
||||||
.dependencies_result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn add_package_reqs(
|
|
||||||
&self,
|
|
||||||
packages: &[PackageReq],
|
|
||||||
caching: PackageCaching<'_>,
|
|
||||||
) -> Result<(), JsErrorBox> {
|
|
||||||
self
|
|
||||||
.add_package_reqs_raw(packages, Some(caching))
|
|
||||||
.await
|
|
||||||
.dependencies_result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn add_package_reqs_raw<'a>(
|
|
||||||
&self,
|
|
||||||
packages: &[PackageReq],
|
|
||||||
caching: Option<PackageCaching<'a>>,
|
|
||||||
) -> AddPkgReqsResult {
|
|
||||||
if packages.is_empty() {
|
|
||||||
return AddPkgReqsResult {
|
|
||||||
dependencies_result: Ok(()),
|
|
||||||
results: vec![],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut result = self.resolution_installer.add_package_reqs(packages).await;
|
|
||||||
|
|
||||||
if result.dependencies_result.is_ok() {
|
|
||||||
if let Some(lockfile) = self.maybe_lockfile.as_ref() {
|
|
||||||
result.dependencies_result = lockfile.error_if_changed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if result.dependencies_result.is_ok() {
|
|
||||||
if let Some(caching) = caching {
|
|
||||||
result.dependencies_result = self.cache_packages(caching).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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_installer.set_package_reqs(packages).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn snapshot(&self) -> NpmResolutionSnapshot {
|
|
||||||
self.resolution.snapshot()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn top_package_req_for_name(&self, name: &str) -> Option<PackageReq> {
|
|
||||||
let package_reqs = self.resolution.package_reqs();
|
|
||||||
let mut entries = package_reqs
|
|
||||||
.iter()
|
|
||||||
.filter(|(_, nv)| nv.name == name)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
entries.sort_by_key(|(_, nv)| &nv.version);
|
|
||||||
Some(entries.last()?.0.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn serialized_valid_snapshot_for_system(
|
|
||||||
&self,
|
|
||||||
system_info: &NpmSystemInfo,
|
|
||||||
) -> ValidSerializedNpmResolutionSnapshot {
|
|
||||||
self
|
|
||||||
.resolution
|
|
||||||
.serialized_valid_snapshot_for_system(system_info)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn inject_synthetic_types_node_package(
|
|
||||||
&self,
|
|
||||||
) -> Result<(), JsErrorBox> {
|
|
||||||
let reqs = &[PackageReq::from_str("@types/node").unwrap()];
|
|
||||||
// add and ensure this isn't added to the lockfile
|
|
||||||
self
|
|
||||||
.add_package_reqs(reqs, PackageCaching::Only(reqs.into()))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn cache_packages(
|
|
||||||
&self,
|
|
||||||
caching: PackageCaching<'_>,
|
|
||||||
) -> Result<(), JsErrorBox> {
|
|
||||||
self.fs_installer.cache_packages(caching).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_pkg_folder_from_deno_module(
|
|
||||||
&self,
|
|
||||||
nv: &PackageNv,
|
|
||||||
) -> Result<PathBuf, ResolvePkgFolderFromDenoModuleError> {
|
|
||||||
let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(nv)?;
|
|
||||||
Ok(self.resolve_pkg_folder_from_pkg_id(&pkg_id)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_pkg_id_from_pkg_req(
|
|
||||||
&self,
|
|
||||||
req: &PackageReq,
|
|
||||||
) -> Result<NpmPackageId, PackageReqNotFoundError> {
|
|
||||||
self.resolution.resolve_pkg_id_from_pkg_req(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ensure_no_pkg_json_dep_errors(
|
|
||||||
&self,
|
|
||||||
) -> Result<(), Box<PackageJsonDepValueParseWithLocationError>> {
|
|
||||||
for err in self.npm_install_deps_provider.pkg_json_dep_errors() {
|
|
||||||
match err.source.as_kind() {
|
|
||||||
deno_package_json::PackageJsonDepValueParseErrorKind::VersionReq(_) => {
|
|
||||||
return Err(Box::new(err.clone()));
|
|
||||||
}
|
|
||||||
deno_package_json::PackageJsonDepValueParseErrorKind::Unsupported {
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
// only warn for this one
|
|
||||||
log::warn!(
|
|
||||||
"{} {}\n at {}",
|
|
||||||
colors::yellow("Warning"),
|
|
||||||
err.source,
|
|
||||||
err.location,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ensures that the top level `package.json` dependencies are installed.
|
|
||||||
/// This may set up the `node_modules` directory.
|
|
||||||
///
|
|
||||||
/// Returns `true` if the top level packages are already installed. A
|
|
||||||
/// return value of `false` means that new packages were added to the NPM resolution.
|
|
||||||
pub async fn ensure_top_level_package_json_install(
|
|
||||||
&self,
|
|
||||||
) -> Result<bool, JsErrorBox> {
|
|
||||||
if !self.top_level_install_flag.raise() {
|
|
||||||
return Ok(true); // already did this
|
|
||||||
}
|
|
||||||
|
|
||||||
let pkg_json_remote_pkgs = self.npm_install_deps_provider.remote_pkgs();
|
|
||||||
if pkg_json_remote_pkgs.is_empty() {
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if something needs resolving before bothering to load all
|
|
||||||
// the package information (which is slow)
|
|
||||||
if pkg_json_remote_pkgs.iter().all(|pkg| {
|
|
||||||
self
|
|
||||||
.resolution
|
|
||||||
.resolve_pkg_id_from_pkg_req(&pkg.req)
|
|
||||||
.is_ok()
|
|
||||||
}) {
|
|
||||||
log::debug!(
|
|
||||||
"All package.json deps resolvable. Skipping top level install."
|
|
||||||
);
|
|
||||||
return Ok(true); // everything is already resolvable
|
|
||||||
}
|
|
||||||
|
|
||||||
let pkg_reqs = pkg_json_remote_pkgs
|
|
||||||
.iter()
|
|
||||||
.map(|pkg| pkg.req.clone())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
self.add_package_reqs_no_cache(&pkg_reqs).await?;
|
|
||||||
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn cache_package_info(
|
|
||||||
&self,
|
|
||||||
package_name: &str,
|
|
||||||
) -> Result<Arc<NpmPackageInfo>, AnyError> {
|
|
||||||
// this will internally cache the package information
|
|
||||||
self
|
|
||||||
.registry_info_provider
|
|
||||||
.package_info(package_name)
|
|
||||||
.await
|
|
||||||
.map_err(|err| err.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn maybe_node_modules_path(&self) -> Option<&Path> {
|
|
||||||
self.managed_npm_resolver.node_modules_path()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn global_cache_root_path(&self) -> &Path {
|
|
||||||
self.npm_cache_dir.root_dir()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn global_cache_root_url(&self) -> &Url {
|
|
||||||
self.npm_cache_dir.root_dir_url()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn npm_process_state(
|
|
||||||
snapshot: ValidSerializedNpmResolutionSnapshot,
|
|
||||||
node_modules_path: Option<&Path>,
|
|
||||||
) -> String {
|
|
||||||
serde_json::to_string(&NpmProcessState {
|
|
||||||
kind: NpmProcessStateKind::Snapshot(snapshot.into_serialized()),
|
|
||||||
local_node_modules_path: node_modules_path
|
|
||||||
.map(|p| p.to_string_lossy().to_string()),
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NpmProcessStateProvider for ManagedCliNpmResolver {
|
|
||||||
fn get_npm_process_state(&self) -> String {
|
|
||||||
npm_process_state(
|
|
||||||
self.resolution.serialized_valid_snapshot(),
|
|
||||||
self.managed_npm_resolver.node_modules_path(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CliNpmResolver for ManagedCliNpmResolver {
|
|
||||||
fn into_npm_pkg_folder_resolver(
|
|
||||||
self: Arc<Self>,
|
|
||||||
) -> Arc<dyn NpmPackageFolderResolver> {
|
|
||||||
self.managed_npm_resolver.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_process_state_provider(
|
|
||||||
self: Arc<Self>,
|
|
||||||
) -> Arc<dyn NpmProcessStateProvider> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_byonm_or_managed(
|
|
||||||
self: Arc<Self>,
|
|
||||||
) -> ByonmOrManagedNpmResolver<CliSys> {
|
|
||||||
ByonmOrManagedNpmResolver::Managed(self.managed_npm_resolver.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver> {
|
|
||||||
// create a new snapshotted npm resolution and resolver
|
|
||||||
let npm_resolution =
|
|
||||||
Arc::new(NpmResolution::new(self.resolution.snapshot()));
|
|
||||||
|
|
||||||
Arc::new(ManagedCliNpmResolver::new(
|
|
||||||
create_npm_fs_installer(
|
|
||||||
self.npm_cache.clone(),
|
|
||||||
&self.npm_install_deps_provider,
|
|
||||||
&self.text_only_progress_bar,
|
|
||||||
npm_resolution.clone(),
|
|
||||||
self.sys.clone(),
|
|
||||||
self.tarball_cache.clone(),
|
|
||||||
self.root_node_modules_path().map(ToOwned::to_owned),
|
|
||||||
self.npm_system_info.clone(),
|
|
||||||
self.lifecycle_scripts.clone(),
|
|
||||||
),
|
|
||||||
self.maybe_lockfile.clone(),
|
|
||||||
Arc::new(ManagedNpmResolver::<CliSys>::new::<CliSys>(
|
|
||||||
&self.npm_cache_dir,
|
|
||||||
&self.npm_rc,
|
|
||||||
npm_resolution.clone(),
|
|
||||||
self.sys.clone(),
|
|
||||||
self.root_node_modules_path().map(ToOwned::to_owned),
|
|
||||||
)),
|
|
||||||
self.npm_cache.clone(),
|
|
||||||
self.npm_cache_dir.clone(),
|
|
||||||
self.npm_install_deps_provider.clone(),
|
|
||||||
self.npm_rc.clone(),
|
|
||||||
self.registry_info_provider.clone(),
|
|
||||||
npm_resolution,
|
|
||||||
self.sys.clone(),
|
|
||||||
self.tarball_cache.clone(),
|
|
||||||
self.text_only_progress_bar.clone(),
|
|
||||||
self.npm_system_info.clone(),
|
|
||||||
self.lifecycle_scripts.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_inner(&self) -> InnerCliNpmResolverRef {
|
|
||||||
InnerCliNpmResolverRef::Managed(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn root_node_modules_path(&self) -> Option<&Path> {
|
|
||||||
self.managed_npm_resolver.node_modules_path()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_state_hash(&self) -> Option<u64> {
|
|
||||||
// We could go further and check all the individual
|
|
||||||
// npm packages, but that's probably overkill.
|
|
||||||
let mut package_reqs = self
|
|
||||||
.resolution
|
|
||||||
.package_reqs()
|
|
||||||
.into_iter()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
package_reqs.sort_by(|a, b| a.0.cmp(&b.0)); // determinism
|
|
||||||
let mut hasher = FastInsecureHasher::new_without_deno_version();
|
|
||||||
// ensure the cache gets busted when turning nodeModulesDir on or off
|
|
||||||
// as this could cause changes in resolution
|
|
||||||
hasher
|
|
||||||
.write_hashable(self.managed_npm_resolver.node_modules_path().is_some());
|
|
||||||
for (pkg_req, pkg_nv) in package_reqs {
|
|
||||||
hasher.write_hashable(&pkg_req);
|
|
||||||
hasher.write_hashable(&pkg_nv);
|
|
||||||
}
|
|
||||||
Some(hasher.finish())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_pkg_folder_from_deno_module_req(
|
|
||||||
&self,
|
|
||||||
req: &PackageReq,
|
|
||||||
referrer: &Url,
|
|
||||||
) -> Result<PathBuf, ResolvePkgFolderFromDenoReqError> {
|
|
||||||
self
|
|
||||||
.managed_npm_resolver
|
|
||||||
.resolve_pkg_folder_from_deno_module_req(req, referrer)
|
|
||||||
.map_err(ResolvePkgFolderFromDenoReqError::Managed)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
mod byonm;
|
mod byonm;
|
||||||
|
pub mod installer;
|
||||||
mod managed;
|
mod managed;
|
||||||
mod permission_checker;
|
mod permission_checker;
|
||||||
|
|
||||||
|
@ -9,7 +10,6 @@ use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
|
@ -30,8 +30,8 @@ pub use self::byonm::CliByonmNpmResolverCreateOptions;
|
||||||
pub use self::managed::CliManagedNpmResolverCreateOptions;
|
pub use self::managed::CliManagedNpmResolverCreateOptions;
|
||||||
pub use self::managed::CliNpmResolverManagedSnapshotOption;
|
pub use self::managed::CliNpmResolverManagedSnapshotOption;
|
||||||
pub use self::managed::ManagedCliNpmResolver;
|
pub use self::managed::ManagedCliNpmResolver;
|
||||||
pub use self::managed::PackageCaching;
|
pub use self::managed::NpmResolutionInitializer;
|
||||||
pub use self::managed::ResolvePkgFolderFromDenoModuleError;
|
pub use self::managed::ResolveSnapshotError;
|
||||||
pub use self::permission_checker::NpmRegistryReadPermissionChecker;
|
pub use self::permission_checker::NpmRegistryReadPermissionChecker;
|
||||||
pub use self::permission_checker::NpmRegistryReadPermissionCheckerMode;
|
pub use self::permission_checker::NpmRegistryReadPermissionCheckerMode;
|
||||||
use crate::file_fetcher::CliFileFetcher;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
|
@ -109,28 +109,16 @@ pub enum CliNpmResolverCreateOptions {
|
||||||
Byonm(CliByonmNpmResolverCreateOptions),
|
Byonm(CliByonmNpmResolverCreateOptions),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_cli_npm_resolver_for_lsp(
|
pub fn create_cli_npm_resolver(
|
||||||
options: CliNpmResolverCreateOptions,
|
options: CliNpmResolverCreateOptions,
|
||||||
) -> Arc<dyn CliNpmResolver> {
|
) -> Arc<dyn CliNpmResolver> {
|
||||||
use CliNpmResolverCreateOptions::*;
|
use CliNpmResolverCreateOptions::*;
|
||||||
match options {
|
match options {
|
||||||
Managed(options) => {
|
Managed(options) => managed::create_managed_npm_resolver(options),
|
||||||
managed::create_managed_npm_resolver_for_lsp(options).await
|
|
||||||
}
|
|
||||||
Byonm(options) => Arc::new(ByonmNpmResolver::new(options)),
|
Byonm(options) => Arc::new(ByonmNpmResolver::new(options)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_cli_npm_resolver(
|
|
||||||
options: CliNpmResolverCreateOptions,
|
|
||||||
) -> Result<Arc<dyn CliNpmResolver>, AnyError> {
|
|
||||||
use CliNpmResolverCreateOptions::*;
|
|
||||||
match options {
|
|
||||||
Managed(options) => managed::create_managed_npm_resolver(options).await,
|
|
||||||
Byonm(options) => Ok(Arc::new(ByonmNpmResolver::new(options))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum InnerCliNpmResolverRef<'a> {
|
pub enum InnerCliNpmResolverRef<'a> {
|
||||||
Managed(&'a ManagedCliNpmResolver),
|
Managed(&'a ManagedCliNpmResolver),
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
107
cli/resolver.rs
107
cli/resolver.rs
|
@ -33,8 +33,8 @@ use thiserror::Error;
|
||||||
use crate::args::NpmCachingStrategy;
|
use crate::args::NpmCachingStrategy;
|
||||||
use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS;
|
use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS;
|
||||||
use crate::node::CliNodeCodeTranslator;
|
use crate::node::CliNodeCodeTranslator;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::installer::NpmInstaller;
|
||||||
use crate::npm::InnerCliNpmResolverRef;
|
use crate::npm::installer::PackageCaching;
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
use crate::util::sync::AtomicFlag;
|
use crate::util::sync::AtomicFlag;
|
||||||
use crate::util::text_encoding::from_utf8_lossy_cow;
|
use crate::util::text_encoding::from_utf8_lossy_cow;
|
||||||
|
@ -164,48 +164,30 @@ impl NpmModuleLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CliResolverOptions {
|
#[derive(Debug, Default)]
|
||||||
pub deno_resolver: Arc<CliDenoResolver>,
|
pub struct FoundPackageJsonDepFlag(AtomicFlag);
|
||||||
pub npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
|
||||||
pub bare_node_builtins_enabled: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A resolver that takes care of resolution, taking into account loaded
|
/// A resolver that takes care of resolution, taking into account loaded
|
||||||
/// import map, JSX settings.
|
/// import map, JSX settings.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CliResolver {
|
pub struct CliResolver {
|
||||||
deno_resolver: Arc<CliDenoResolver>,
|
deno_resolver: Arc<CliDenoResolver>,
|
||||||
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
found_package_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
|
||||||
found_package_json_dep_flag: AtomicFlag,
|
|
||||||
bare_node_builtins_enabled: bool,
|
|
||||||
warned_pkgs: DashSet<PackageReq>,
|
warned_pkgs: DashSet<PackageReq>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliResolver {
|
impl CliResolver {
|
||||||
pub fn new(options: CliResolverOptions) -> Self {
|
pub fn new(
|
||||||
|
deno_resolver: Arc<CliDenoResolver>,
|
||||||
|
found_package_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
deno_resolver: options.deno_resolver,
|
deno_resolver,
|
||||||
npm_resolver: options.npm_resolver,
|
found_package_json_dep_flag,
|
||||||
found_package_json_dep_flag: Default::default(),
|
|
||||||
bare_node_builtins_enabled: options.bare_node_builtins_enabled,
|
|
||||||
warned_pkgs: Default::default(),
|
warned_pkgs: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(dsherret): move this off CliResolver as CliResolver is acting
|
|
||||||
// like a factory by doing this (it's beyond its responsibility)
|
|
||||||
pub fn create_graph_npm_resolver(
|
|
||||||
&self,
|
|
||||||
npm_caching: NpmCachingStrategy,
|
|
||||||
) -> WorkerCliNpmGraphResolver {
|
|
||||||
WorkerCliNpmGraphResolver {
|
|
||||||
npm_resolver: self.npm_resolver.as_ref(),
|
|
||||||
found_package_json_dep_flag: &self.found_package_json_dep_flag,
|
|
||||||
bare_node_builtins_enabled: self.bare_node_builtins_enabled,
|
|
||||||
npm_caching,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve(
|
pub fn resolve(
|
||||||
&self,
|
&self,
|
||||||
raw_specifier: &str,
|
raw_specifier: &str,
|
||||||
|
@ -233,7 +215,7 @@ impl CliResolver {
|
||||||
|
|
||||||
if resolution.found_package_json_dep {
|
if resolution.found_package_json_dep {
|
||||||
// mark that we need to do an "npm install" later
|
// mark that we need to do an "npm install" later
|
||||||
self.found_package_json_dep_flag.raise();
|
self.found_package_json_dep_flag.0.raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(diagnostic) = resolution.maybe_diagnostic {
|
if let Some(diagnostic) = resolution.maybe_diagnostic {
|
||||||
|
@ -260,15 +242,31 @@ impl CliResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct WorkerCliNpmGraphResolver<'a> {
|
pub struct CliNpmGraphResolver {
|
||||||
npm_resolver: Option<&'a Arc<dyn CliNpmResolver>>,
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
found_package_json_dep_flag: &'a AtomicFlag,
|
found_package_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
|
||||||
bare_node_builtins_enabled: bool,
|
bare_node_builtins_enabled: bool,
|
||||||
npm_caching: NpmCachingStrategy,
|
npm_caching: NpmCachingStrategy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CliNpmGraphResolver {
|
||||||
|
pub fn new(
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
|
found_package_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
|
||||||
|
bare_node_builtins_enabled: bool,
|
||||||
|
npm_caching: NpmCachingStrategy,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
npm_installer,
|
||||||
|
found_package_json_dep_flag,
|
||||||
|
bare_node_builtins_enabled,
|
||||||
|
npm_caching,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> {
|
impl deno_graph::source::NpmResolver for CliNpmGraphResolver {
|
||||||
fn resolve_builtin_node_module(
|
fn resolve_builtin_node_module(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
@ -298,17 +296,12 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_and_cache_npm_package_info(&self, package_name: &str) {
|
fn load_and_cache_npm_package_info(&self, package_name: &str) {
|
||||||
match self.npm_resolver {
|
if let Some(npm_installer) = &self.npm_installer {
|
||||||
Some(npm_resolver) if npm_resolver.as_managed().is_some() => {
|
let npm_installer = npm_installer.clone();
|
||||||
let npm_resolver = npm_resolver.clone();
|
let package_name = package_name.to_string();
|
||||||
let package_name = package_name.to_string();
|
deno_core::unsync::spawn(async move {
|
||||||
deno_core::unsync::spawn(async move {
|
let _ignore = npm_installer.cache_package_info(&package_name).await;
|
||||||
if let Some(managed) = npm_resolver.as_managed() {
|
});
|
||||||
let _ignore = managed.cache_package_info(&package_name).await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,17 +309,11 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> {
|
||||||
&self,
|
&self,
|
||||||
package_reqs: &[PackageReq],
|
package_reqs: &[PackageReq],
|
||||||
) -> NpmResolvePkgReqsResult {
|
) -> NpmResolvePkgReqsResult {
|
||||||
match &self.npm_resolver {
|
match &self.npm_installer {
|
||||||
Some(npm_resolver) => {
|
Some(npm_installer) => {
|
||||||
let npm_resolver = match npm_resolver.as_inner() {
|
let top_level_result = if self.found_package_json_dep_flag.0.is_raised()
|
||||||
InnerCliNpmResolverRef::Managed(npm_resolver) => npm_resolver,
|
{
|
||||||
// if we are using byonm, then this should never be called because
|
npm_installer
|
||||||
// we don't use deno_graph's npm resolution in this case
|
|
||||||
InnerCliNpmResolverRef::Byonm(_) => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let top_level_result = if self.found_package_json_dep_flag.is_raised() {
|
|
||||||
npm_resolver
|
|
||||||
.ensure_top_level_package_json_install()
|
.ensure_top_level_package_json_install()
|
||||||
.await
|
.await
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
|
@ -334,15 +321,13 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = npm_resolver
|
let result = npm_installer
|
||||||
.add_package_reqs_raw(
|
.add_package_reqs_raw(
|
||||||
package_reqs,
|
package_reqs,
|
||||||
match self.npm_caching {
|
match self.npm_caching {
|
||||||
NpmCachingStrategy::Eager => {
|
NpmCachingStrategy::Eager => Some(PackageCaching::All),
|
||||||
Some(crate::npm::PackageCaching::All)
|
|
||||||
}
|
|
||||||
NpmCachingStrategy::Lazy => {
|
NpmCachingStrategy::Lazy => {
|
||||||
Some(crate::npm::PackageCaching::Only(package_reqs.into()))
|
Some(PackageCaching::Only(package_reqs.into()))
|
||||||
}
|
}
|
||||||
NpmCachingStrategy::Manual => None,
|
NpmCachingStrategy::Manual => None,
|
||||||
},
|
},
|
||||||
|
|
|
@ -37,10 +37,12 @@ use deno_core::ResolutionKind;
|
||||||
use deno_core::SourceCodeCacheInfo;
|
use deno_core::SourceCodeCacheInfo;
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
|
use deno_npm::resolution::NpmResolutionSnapshot;
|
||||||
use deno_package_json::PackageJsonDepValue;
|
use deno_package_json::PackageJsonDepValue;
|
||||||
use deno_resolver::cjs::IsCjsResolutionMode;
|
use deno_resolver::cjs::IsCjsResolutionMode;
|
||||||
use deno_resolver::npm::create_in_npm_pkg_checker;
|
use deno_resolver::npm::create_in_npm_pkg_checker;
|
||||||
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
|
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
|
||||||
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
||||||
use deno_resolver::npm::NpmReqResolverOptions;
|
use deno_resolver::npm::NpmReqResolverOptions;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
|
@ -91,6 +93,7 @@ use crate::npm::CliNpmResolverCreateOptions;
|
||||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||||
use crate::npm::NpmRegistryReadPermissionChecker;
|
use crate::npm::NpmRegistryReadPermissionChecker;
|
||||||
use crate::npm::NpmRegistryReadPermissionCheckerMode;
|
use crate::npm::NpmRegistryReadPermissionCheckerMode;
|
||||||
|
use crate::npm::NpmResolutionInitializer;
|
||||||
use crate::resolver::CjsTracker;
|
use crate::resolver::CjsTracker;
|
||||||
use crate::resolver::CliNpmReqResolver;
|
use crate::resolver::CliNpmReqResolver;
|
||||||
use crate::resolver::NpmModuleLoader;
|
use crate::resolver::NpmModuleLoader;
|
||||||
|
@ -687,18 +690,12 @@ pub async fn run(
|
||||||
ca_data: metadata.ca_data.map(CaData::Bytes),
|
ca_data: metadata.ca_data.map(CaData::Bytes),
|
||||||
cell: Default::default(),
|
cell: Default::default(),
|
||||||
});
|
});
|
||||||
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
|
|
||||||
let http_client_provider = Arc::new(HttpClientProvider::new(
|
|
||||||
Some(root_cert_store_provider.clone()),
|
|
||||||
metadata.unsafely_ignore_certificate_errors.clone(),
|
|
||||||
));
|
|
||||||
// use a dummy npm registry url
|
// use a dummy npm registry url
|
||||||
let npm_registry_url = ModuleSpecifier::parse("https://localhost/").unwrap();
|
let npm_registry_url = ModuleSpecifier::parse("https://localhost/").unwrap();
|
||||||
let root_dir_url =
|
let root_dir_url =
|
||||||
Arc::new(ModuleSpecifier::from_directory_path(&root_path).unwrap());
|
Arc::new(ModuleSpecifier::from_directory_path(&root_path).unwrap());
|
||||||
let main_module = root_dir_url.join(&metadata.entrypoint_key).unwrap();
|
let main_module = root_dir_url.join(&metadata.entrypoint_key).unwrap();
|
||||||
let npm_global_cache_dir = root_path.join(".deno_compile_node_modules");
|
let npm_global_cache_dir = root_path.join(".deno_compile_node_modules");
|
||||||
let cache_setting = CacheSetting::Only;
|
|
||||||
let pkg_json_resolver = Arc::new(CliPackageJsonResolver::new(sys.clone()));
|
let pkg_json_resolver = Arc::new(CliPackageJsonResolver::new(sys.clone()));
|
||||||
let npm_registry_permission_checker = {
|
let npm_registry_permission_checker = {
|
||||||
let mode = match &metadata.node_modules {
|
let mode = match &metadata.node_modules {
|
||||||
|
@ -743,29 +740,19 @@ pub async fn run(
|
||||||
maybe_node_modules_path: maybe_node_modules_path.as_deref(),
|
maybe_node_modules_path: maybe_node_modules_path.as_deref(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
let npm_resolution =
|
||||||
|
Arc::new(NpmResolutionCell::new(NpmResolutionSnapshot::new(snapshot)));
|
||||||
let npm_resolver =
|
let npm_resolver =
|
||||||
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
|
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
|
||||||
CliManagedNpmResolverCreateOptions {
|
CliManagedNpmResolverCreateOptions {
|
||||||
snapshot: CliNpmResolverManagedSnapshotOption::Specified(Some(
|
npm_resolution,
|
||||||
snapshot,
|
|
||||||
)),
|
|
||||||
maybe_lockfile: None,
|
|
||||||
http_client_provider: http_client_provider.clone(),
|
|
||||||
npm_cache_dir,
|
npm_cache_dir,
|
||||||
npm_install_deps_provider: Arc::new(
|
|
||||||
// this is only used for installing packages, which isn't necessary with deno compile
|
|
||||||
NpmInstallDepsProvider::empty(),
|
|
||||||
),
|
|
||||||
sys: sys.clone(),
|
sys: sys.clone(),
|
||||||
text_only_progress_bar: progress_bar,
|
|
||||||
cache_setting,
|
|
||||||
maybe_node_modules_path,
|
maybe_node_modules_path,
|
||||||
npm_system_info: Default::default(),
|
npm_system_info: Default::default(),
|
||||||
npmrc,
|
npmrc,
|
||||||
lifecycle_scripts: Default::default(),
|
|
||||||
},
|
},
|
||||||
))
|
));
|
||||||
.await?;
|
|
||||||
(in_npm_pkg_checker, npm_resolver)
|
(in_npm_pkg_checker, npm_resolver)
|
||||||
}
|
}
|
||||||
Some(binary::NodeModules::Byonm {
|
Some(binary::NodeModules::Byonm {
|
||||||
|
@ -781,8 +768,7 @@ pub async fn run(
|
||||||
pkg_json_resolver: pkg_json_resolver.clone(),
|
pkg_json_resolver: pkg_json_resolver.clone(),
|
||||||
root_node_modules_dir,
|
root_node_modules_dir,
|
||||||
}),
|
}),
|
||||||
)
|
);
|
||||||
.await?;
|
|
||||||
(in_npm_pkg_checker, npm_resolver)
|
(in_npm_pkg_checker, npm_resolver)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -801,27 +787,18 @@ pub async fn run(
|
||||||
maybe_node_modules_path: None,
|
maybe_node_modules_path: None,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
let npm_resolution = Arc::new(NpmResolutionCell::default());
|
||||||
let npm_resolver =
|
let npm_resolver =
|
||||||
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
|
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
|
||||||
CliManagedNpmResolverCreateOptions {
|
CliManagedNpmResolverCreateOptions {
|
||||||
snapshot: CliNpmResolverManagedSnapshotOption::Specified(None),
|
npm_resolution,
|
||||||
http_client_provider: http_client_provider.clone(),
|
|
||||||
npm_install_deps_provider: Arc::new(
|
|
||||||
// this is only used for installing packages, which isn't necessary with deno compile
|
|
||||||
NpmInstallDepsProvider::empty(),
|
|
||||||
),
|
|
||||||
sys: sys.clone(),
|
sys: sys.clone(),
|
||||||
cache_setting,
|
|
||||||
text_only_progress_bar: progress_bar,
|
|
||||||
npm_cache_dir,
|
npm_cache_dir,
|
||||||
maybe_lockfile: None,
|
|
||||||
maybe_node_modules_path: None,
|
maybe_node_modules_path: None,
|
||||||
npm_system_info: Default::default(),
|
npm_system_info: Default::default(),
|
||||||
npmrc: create_default_npmrc(),
|
npmrc: create_default_npmrc(),
|
||||||
lifecycle_scripts: Default::default(),
|
|
||||||
},
|
},
|
||||||
))
|
));
|
||||||
.await?;
|
|
||||||
(in_npm_pkg_checker, npm_resolver)
|
(in_npm_pkg_checker, npm_resolver)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -995,6 +972,7 @@ pub async fn run(
|
||||||
None,
|
None,
|
||||||
Box::new(module_loader_factory),
|
Box::new(module_loader_factory),
|
||||||
node_resolver,
|
node_resolver,
|
||||||
|
None,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
pkg_json_resolver,
|
pkg_json_resolver,
|
||||||
root_cert_store_provider,
|
root_cert_store_provider,
|
||||||
|
|
|
@ -34,6 +34,7 @@ use crate::graph_util::maybe_additional_sloppy_imports_message;
|
||||||
use crate::graph_util::BuildFastCheckGraphOptions;
|
use crate::graph_util::BuildFastCheckGraphOptions;
|
||||||
use crate::graph_util::ModuleGraphBuilder;
|
use crate::graph_util::ModuleGraphBuilder;
|
||||||
use crate::node::CliNodeResolver;
|
use crate::node::CliNodeResolver;
|
||||||
|
use crate::npm::installer::NpmInstaller;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
use crate::tsc;
|
use crate::tsc;
|
||||||
|
@ -109,6 +110,7 @@ pub struct TypeChecker {
|
||||||
cjs_tracker: Arc<TypeCheckingCjsTracker>,
|
cjs_tracker: Arc<TypeCheckingCjsTracker>,
|
||||||
cli_options: Arc<CliOptions>,
|
cli_options: Arc<CliOptions>,
|
||||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<CliNodeResolver>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
sys: CliSys,
|
sys: CliSys,
|
||||||
|
@ -136,12 +138,14 @@ pub enum CheckError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeChecker {
|
impl TypeChecker {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
caches: Arc<Caches>,
|
caches: Arc<Caches>,
|
||||||
cjs_tracker: Arc<TypeCheckingCjsTracker>,
|
cjs_tracker: Arc<TypeCheckingCjsTracker>,
|
||||||
cli_options: Arc<CliOptions>,
|
cli_options: Arc<CliOptions>,
|
||||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<CliNodeResolver>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
sys: CliSys,
|
sys: CliSys,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -151,6 +155,7 @@ impl TypeChecker {
|
||||||
cli_options,
|
cli_options,
|
||||||
module_graph_builder,
|
module_graph_builder,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
|
npm_installer,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
sys,
|
sys,
|
||||||
}
|
}
|
||||||
|
@ -191,9 +196,9 @@ impl TypeChecker {
|
||||||
// node built-in specifiers use the @types/node package to determine
|
// node built-in specifiers use the @types/node package to determine
|
||||||
// types, so inject that now (the caller should do this after the lockfile
|
// types, so inject that now (the caller should do this after the lockfile
|
||||||
// has been written)
|
// has been written)
|
||||||
if let Some(npm_resolver) = self.npm_resolver.as_managed() {
|
if let Some(npm_installer) = &self.npm_installer {
|
||||||
if graph.has_node_specifier {
|
if graph.has_node_specifier {
|
||||||
npm_resolver.inject_synthetic_types_node_package().await?;
|
npm_installer.inject_synthetic_types_node_package().await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -386,8 +386,11 @@ impl NpmInfo {
|
||||||
npm_snapshot: &'a NpmResolutionSnapshot,
|
npm_snapshot: &'a NpmResolutionSnapshot,
|
||||||
) {
|
) {
|
||||||
self.packages.insert(package.id.clone(), package.clone());
|
self.packages.insert(package.id.clone(), package.clone());
|
||||||
if let Ok(size) = npm_resolver.package_size(&package.id) {
|
if let Ok(folder) = npm_resolver.resolve_pkg_folder_from_pkg_id(&package.id)
|
||||||
self.package_sizes.insert(package.id.clone(), size);
|
{
|
||||||
|
if let Ok(size) = crate::util::fs::dir_size(&folder) {
|
||||||
|
self.package_sizes.insert(package.id.clone(), size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for id in package.dependencies.values() {
|
for id in package.dependencies.values() {
|
||||||
if !self.packages.contains_key(id) {
|
if !self.packages.contains_key(id) {
|
||||||
|
|
|
@ -300,8 +300,8 @@ async fn install_local(
|
||||||
InstallFlagsLocal::TopLevel => {
|
InstallFlagsLocal::TopLevel => {
|
||||||
let factory = CliFactory::from_flags(flags);
|
let factory = CliFactory::from_flags(flags);
|
||||||
// surface any errors in the package.json
|
// surface any errors in the package.json
|
||||||
if let Some(npm_resolver) = factory.npm_resolver().await?.as_managed() {
|
if let Some(npm_installer) = factory.npm_installer_if_managed()? {
|
||||||
npm_resolver.ensure_no_pkg_json_dep_errors()?;
|
npm_installer.ensure_no_pkg_json_dep_errors()?;
|
||||||
}
|
}
|
||||||
crate::tools::registry::cache_top_level_deps(&factory, None).await?;
|
crate::tools::registry::cache_top_level_deps(&factory, None).await?;
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub async fn kernel(
|
||||||
// TODO(bartlomieju): should we run with all permissions?
|
// TODO(bartlomieju): should we run with all permissions?
|
||||||
let permissions =
|
let permissions =
|
||||||
PermissionsContainer::allow_all(factory.permission_desc_parser()?.clone());
|
PermissionsContainer::allow_all(factory.permission_desc_parser()?.clone());
|
||||||
let npm_resolver = factory.npm_resolver().await?.clone();
|
let npm_installer = factory.npm_installer_if_managed()?.cloned();
|
||||||
let resolver = factory.resolver().await?.clone();
|
let resolver = factory.resolver().await?.clone();
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
let (stdio_tx, stdio_rx) = mpsc::unbounded_channel();
|
let (stdio_tx, stdio_rx) = mpsc::unbounded_channel();
|
||||||
|
@ -115,7 +115,7 @@ pub async fn kernel(
|
||||||
let worker = worker.into_main_worker();
|
let worker = worker.into_main_worker();
|
||||||
let mut repl_session = repl::ReplSession::initialize(
|
let mut repl_session = repl::ReplSession::initialize(
|
||||||
cli_options,
|
cli_options,
|
||||||
npm_resolver,
|
npm_installer,
|
||||||
resolver,
|
resolver,
|
||||||
worker,
|
worker,
|
||||||
main_module,
|
main_module,
|
||||||
|
|
|
@ -861,10 +861,8 @@ async fn npm_install_after_modification(
|
||||||
// make a new CliFactory to pick up the updated config file
|
// make a new CliFactory to pick up the updated config file
|
||||||
let cli_factory = CliFactory::from_flags(flags);
|
let cli_factory = CliFactory::from_flags(flags);
|
||||||
// surface any errors in the package.json
|
// surface any errors in the package.json
|
||||||
let npm_resolver = cli_factory.npm_resolver().await?;
|
let npm_installer = cli_factory.npm_installer()?;
|
||||||
if let Some(npm_resolver) = npm_resolver.as_managed() {
|
npm_installer.ensure_no_pkg_json_dep_errors()?;
|
||||||
npm_resolver.ensure_no_pkg_json_dep_errors()?;
|
|
||||||
}
|
|
||||||
// npm install
|
// npm install
|
||||||
cache_deps::cache_top_level_deps(&cli_factory, jsr_resolver).await?;
|
cache_deps::cache_top_level_deps(&cli_factory, jsr_resolver).await?;
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,19 @@ use crate::factory::CliFactory;
|
||||||
use crate::graph_container::ModuleGraphContainer;
|
use crate::graph_container::ModuleGraphContainer;
|
||||||
use crate::graph_container::ModuleGraphUpdatePermit;
|
use crate::graph_container::ModuleGraphUpdatePermit;
|
||||||
use crate::graph_util::CreateGraphOptions;
|
use crate::graph_util::CreateGraphOptions;
|
||||||
|
use crate::npm::installer::PackageCaching;
|
||||||
|
|
||||||
pub async fn cache_top_level_deps(
|
pub async fn cache_top_level_deps(
|
||||||
// todo(dsherret): don't pass the factory into this function. Instead use ctor deps
|
// todo(dsherret): don't pass the factory into this function. Instead use ctor deps
|
||||||
factory: &CliFactory,
|
factory: &CliFactory,
|
||||||
jsr_resolver: Option<Arc<crate::jsr::JsrFetchResolver>>,
|
jsr_resolver: Option<Arc<crate::jsr::JsrFetchResolver>>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let npm_resolver = factory.npm_resolver().await?;
|
let npm_installer = factory.npm_installer_if_managed()?;
|
||||||
let cli_options = factory.cli_options()?;
|
let cli_options = factory.cli_options()?;
|
||||||
if let Some(npm_resolver) = npm_resolver.as_managed() {
|
if let Some(npm_installer) = &npm_installer {
|
||||||
npm_resolver.ensure_top_level_package_json_install().await?;
|
npm_installer
|
||||||
|
.ensure_top_level_package_json_install()
|
||||||
|
.await?;
|
||||||
if let Some(lockfile) = cli_options.maybe_lockfile() {
|
if let Some(lockfile) = cli_options.maybe_lockfile() {
|
||||||
lockfile.error_if_changed()?;
|
lockfile.error_if_changed()?;
|
||||||
}
|
}
|
||||||
|
@ -138,10 +141,8 @@ pub async fn cache_top_level_deps(
|
||||||
maybe_graph_error = graph_builder.graph_roots_valid(graph, &roots);
|
maybe_graph_error = graph_builder.graph_roots_valid(graph, &roots);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(npm_resolver) = npm_resolver.as_managed() {
|
if let Some(npm_installer) = &npm_installer {
|
||||||
npm_resolver
|
npm_installer.cache_packages(PackageCaching::All).await?;
|
||||||
.cache_packages(crate::npm::PackageCaching::All)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maybe_graph_error?;
|
maybe_graph_error?;
|
||||||
|
|
|
@ -42,6 +42,7 @@ use crate::graph_container::ModuleGraphContainer;
|
||||||
use crate::graph_container::ModuleGraphUpdatePermit;
|
use crate::graph_container::ModuleGraphUpdatePermit;
|
||||||
use crate::jsr::JsrFetchResolver;
|
use crate::jsr::JsrFetchResolver;
|
||||||
use crate::module_loader::ModuleLoadPreparer;
|
use crate::module_loader::ModuleLoadPreparer;
|
||||||
|
use crate::npm::installer::NpmInstaller;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::npm::NpmFetchResolver;
|
use crate::npm::NpmFetchResolver;
|
||||||
use crate::util::sync::AtomicFlag;
|
use crate::util::sync::AtomicFlag;
|
||||||
|
@ -451,6 +452,7 @@ pub struct DepManager {
|
||||||
pub(crate) jsr_fetch_resolver: Arc<JsrFetchResolver>,
|
pub(crate) jsr_fetch_resolver: Arc<JsrFetchResolver>,
|
||||||
pub(crate) npm_fetch_resolver: Arc<NpmFetchResolver>,
|
pub(crate) npm_fetch_resolver: Arc<NpmFetchResolver>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
|
npm_installer: Arc<NpmInstaller>,
|
||||||
permissions_container: PermissionsContainer,
|
permissions_container: PermissionsContainer,
|
||||||
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
||||||
lockfile: Option<Arc<CliLockfile>>,
|
lockfile: Option<Arc<CliLockfile>>,
|
||||||
|
@ -460,6 +462,7 @@ pub struct DepManagerArgs {
|
||||||
pub module_load_preparer: Arc<ModuleLoadPreparer>,
|
pub module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||||
pub jsr_fetch_resolver: Arc<JsrFetchResolver>,
|
pub jsr_fetch_resolver: Arc<JsrFetchResolver>,
|
||||||
pub npm_fetch_resolver: Arc<NpmFetchResolver>,
|
pub npm_fetch_resolver: Arc<NpmFetchResolver>,
|
||||||
|
pub npm_installer: Arc<NpmInstaller>,
|
||||||
pub npm_resolver: Arc<dyn CliNpmResolver>,
|
pub npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
pub permissions_container: PermissionsContainer,
|
pub permissions_container: PermissionsContainer,
|
||||||
pub main_module_graph_container: Arc<MainModuleGraphContainer>,
|
pub main_module_graph_container: Arc<MainModuleGraphContainer>,
|
||||||
|
@ -477,6 +480,7 @@ impl DepManager {
|
||||||
module_load_preparer,
|
module_load_preparer,
|
||||||
jsr_fetch_resolver,
|
jsr_fetch_resolver,
|
||||||
npm_fetch_resolver,
|
npm_fetch_resolver,
|
||||||
|
npm_installer,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
permissions_container,
|
permissions_container,
|
||||||
main_module_graph_container,
|
main_module_graph_container,
|
||||||
|
@ -490,6 +494,7 @@ impl DepManager {
|
||||||
dependencies_resolved: AtomicFlag::lowered(),
|
dependencies_resolved: AtomicFlag::lowered(),
|
||||||
module_load_preparer,
|
module_load_preparer,
|
||||||
npm_fetch_resolver,
|
npm_fetch_resolver,
|
||||||
|
npm_installer,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
permissions_container,
|
permissions_container,
|
||||||
main_module_graph_container,
|
main_module_graph_container,
|
||||||
|
@ -556,7 +561,10 @@ impl DepManager {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
npm_resolver.ensure_top_level_package_json_install().await?;
|
self
|
||||||
|
.npm_installer
|
||||||
|
.ensure_top_level_package_json_install()
|
||||||
|
.await?;
|
||||||
let mut roots = Vec::new();
|
let mut roots = Vec::new();
|
||||||
let mut info_futures = FuturesUnordered::new();
|
let mut info_futures = FuturesUnordered::new();
|
||||||
for dep in &self.deps {
|
for dep in &self.deps {
|
||||||
|
|
|
@ -445,6 +445,7 @@ async fn dep_manager_args(
|
||||||
jsr_fetch_resolver,
|
jsr_fetch_resolver,
|
||||||
npm_fetch_resolver,
|
npm_fetch_resolver,
|
||||||
npm_resolver: factory.npm_resolver().await?.clone(),
|
npm_resolver: factory.npm_resolver().await?.clone(),
|
||||||
|
npm_installer: factory.npm_installer()?.clone(),
|
||||||
permissions_container: factory.root_permissions_container()?.clone(),
|
permissions_container: factory.root_permissions_container()?.clone(),
|
||||||
main_module_graph_container: factory
|
main_module_graph_container: factory
|
||||||
.main_module_graph_container()
|
.main_module_graph_container()
|
||||||
|
|
|
@ -164,7 +164,7 @@ pub async fn run(
|
||||||
let cli_options = factory.cli_options()?;
|
let cli_options = factory.cli_options()?;
|
||||||
let main_module = cli_options.resolve_main_module()?;
|
let main_module = cli_options.resolve_main_module()?;
|
||||||
let permissions = factory.root_permissions_container()?;
|
let permissions = factory.root_permissions_container()?;
|
||||||
let npm_resolver = factory.npm_resolver().await?.clone();
|
let npm_installer = factory.npm_installer_if_managed()?.cloned();
|
||||||
let resolver = factory.resolver().await?.clone();
|
let resolver = factory.resolver().await?.clone();
|
||||||
let file_fetcher = factory.file_fetcher()?;
|
let file_fetcher = factory.file_fetcher()?;
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
|
@ -187,7 +187,7 @@ pub async fn run(
|
||||||
let worker = worker.into_main_worker();
|
let worker = worker.into_main_worker();
|
||||||
let session = ReplSession::initialize(
|
let session = ReplSession::initialize(
|
||||||
cli_options,
|
cli_options,
|
||||||
npm_resolver,
|
npm_installer,
|
||||||
resolver,
|
resolver,
|
||||||
worker,
|
worker,
|
||||||
main_module.clone(),
|
main_module.clone(),
|
||||||
|
|
|
@ -45,7 +45,7 @@ use crate::args::CliOptions;
|
||||||
use crate::cdp;
|
use crate::cdp;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::lsp::ReplLanguageServer;
|
use crate::lsp::ReplLanguageServer;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::installer::NpmInstaller;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
use crate::tools::test::report_tests;
|
use crate::tools::test::report_tests;
|
||||||
use crate::tools::test::reporters::PrettyTestReporter;
|
use crate::tools::test::reporters::PrettyTestReporter;
|
||||||
|
@ -181,7 +181,7 @@ struct ReplJsxState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReplSession {
|
pub struct ReplSession {
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
resolver: Arc<CliResolver>,
|
resolver: Arc<CliResolver>,
|
||||||
pub worker: MainWorker,
|
pub worker: MainWorker,
|
||||||
session: LocalInspectorSession,
|
session: LocalInspectorSession,
|
||||||
|
@ -200,7 +200,7 @@ pub struct ReplSession {
|
||||||
impl ReplSession {
|
impl ReplSession {
|
||||||
pub async fn initialize(
|
pub async fn initialize(
|
||||||
cli_options: &CliOptions,
|
cli_options: &CliOptions,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
resolver: Arc<CliResolver>,
|
resolver: Arc<CliResolver>,
|
||||||
mut worker: MainWorker,
|
mut worker: MainWorker,
|
||||||
main_module: ModuleSpecifier,
|
main_module: ModuleSpecifier,
|
||||||
|
@ -265,7 +265,7 @@ impl ReplSession {
|
||||||
)?;
|
)?;
|
||||||
let experimental_decorators = transpile_options.use_ts_decorators;
|
let experimental_decorators = transpile_options.use_ts_decorators;
|
||||||
let mut repl_session = ReplSession {
|
let mut repl_session = ReplSession {
|
||||||
npm_resolver,
|
npm_installer,
|
||||||
resolver,
|
resolver,
|
||||||
worker,
|
worker,
|
||||||
session,
|
session,
|
||||||
|
@ -704,8 +704,8 @@ impl ReplSession {
|
||||||
&mut self,
|
&mut self,
|
||||||
program: &swc_ast::Program,
|
program: &swc_ast::Program,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let Some(npm_resolver) = self.npm_resolver.as_managed() else {
|
let Some(npm_installer) = &self.npm_installer else {
|
||||||
return Ok(()); // don't auto-install for byonm
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut collector = ImportCollector::new();
|
let mut collector = ImportCollector::new();
|
||||||
|
@ -737,13 +737,13 @@ impl ReplSession {
|
||||||
let has_node_specifier =
|
let has_node_specifier =
|
||||||
resolved_imports.iter().any(|url| url.scheme() == "node");
|
resolved_imports.iter().any(|url| url.scheme() == "node");
|
||||||
if !npm_imports.is_empty() || has_node_specifier {
|
if !npm_imports.is_empty() || has_node_specifier {
|
||||||
npm_resolver
|
npm_installer
|
||||||
.add_and_cache_package_reqs(&npm_imports)
|
.add_and_cache_package_reqs(&npm_imports)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// prevent messages in the repl about @types/node not being cached
|
// prevent messages in the repl about @types/node not being cached
|
||||||
if has_node_specifier {
|
if has_node_specifier {
|
||||||
npm_resolver.inject_synthetic_types_node_package().await?;
|
npm_installer.inject_synthetic_types_node_package().await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::args::EvalFlags;
|
||||||
use crate::args::Flags;
|
use crate::args::Flags;
|
||||||
use crate::args::WatchFlagsWithPaths;
|
use crate::args::WatchFlagsWithPaths;
|
||||||
use crate::factory::CliFactory;
|
use crate::factory::CliFactory;
|
||||||
|
use crate::npm::installer::PackageCaching;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use crate::util::file_watcher::WatcherRestartMode;
|
use crate::util::file_watcher::WatcherRestartMode;
|
||||||
|
|
||||||
|
@ -202,18 +203,17 @@ pub async fn maybe_npm_install(factory: &CliFactory) -> Result<(), AnyError> {
|
||||||
// ensure an "npm install" is done if the user has explicitly
|
// ensure an "npm install" is done if the user has explicitly
|
||||||
// opted into using a managed node_modules directory
|
// opted into using a managed node_modules directory
|
||||||
if cli_options.node_modules_dir()? == Some(NodeModulesDirMode::Auto) {
|
if cli_options.node_modules_dir()? == Some(NodeModulesDirMode::Auto) {
|
||||||
if let Some(npm_resolver) = factory.npm_resolver().await?.as_managed() {
|
if let Some(npm_installer) = factory.npm_installer_if_managed()? {
|
||||||
let already_done =
|
let already_done = npm_installer
|
||||||
npm_resolver.ensure_top_level_package_json_install().await?;
|
.ensure_top_level_package_json_install()
|
||||||
|
.await?;
|
||||||
if !already_done
|
if !already_done
|
||||||
&& matches!(
|
&& matches!(
|
||||||
cli_options.default_npm_caching_strategy(),
|
cli_options.default_npm_caching_strategy(),
|
||||||
crate::graph_util::NpmCachingStrategy::Eager
|
crate::graph_util::NpmCachingStrategy::Eager
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
npm_resolver
|
npm_installer.cache_packages(PackageCaching::All).await?;
|
||||||
.cache_packages(crate::npm::PackageCaching::All)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ use crate::args::TaskFlags;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::factory::CliFactory;
|
use crate::factory::CliFactory;
|
||||||
use crate::node::CliNodeResolver;
|
use crate::node::CliNodeResolver;
|
||||||
|
use crate::npm::installer::NpmInstaller;
|
||||||
|
use crate::npm::installer::PackageCaching;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::task_runner;
|
use crate::task_runner;
|
||||||
use crate::task_runner::run_future_forwarding_signals;
|
use crate::task_runner::run_future_forwarding_signals;
|
||||||
|
@ -203,6 +205,7 @@ pub async fn execute_script(
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let npm_installer = factory.npm_installer_if_managed()?;
|
||||||
let npm_resolver = factory.npm_resolver().await?;
|
let npm_resolver = factory.npm_resolver().await?;
|
||||||
let node_resolver = factory.node_resolver().await?;
|
let node_resolver = factory.node_resolver().await?;
|
||||||
let env_vars = task_runner::real_env_vars();
|
let env_vars = task_runner::real_env_vars();
|
||||||
|
@ -216,6 +219,7 @@ pub async fn execute_script(
|
||||||
|
|
||||||
let task_runner = TaskRunner {
|
let task_runner = TaskRunner {
|
||||||
task_flags: &task_flags,
|
task_flags: &task_flags,
|
||||||
|
npm_installer: npm_installer.map(|n| n.as_ref()),
|
||||||
npm_resolver: npm_resolver.as_ref(),
|
npm_resolver: npm_resolver.as_ref(),
|
||||||
node_resolver: node_resolver.as_ref(),
|
node_resolver: node_resolver.as_ref(),
|
||||||
env_vars,
|
env_vars,
|
||||||
|
@ -266,6 +270,7 @@ struct RunSingleOptions<'a> {
|
||||||
|
|
||||||
struct TaskRunner<'a> {
|
struct TaskRunner<'a> {
|
||||||
task_flags: &'a TaskFlags,
|
task_flags: &'a TaskFlags,
|
||||||
|
npm_installer: Option<&'a NpmInstaller>,
|
||||||
npm_resolver: &'a dyn CliNpmResolver,
|
npm_resolver: &'a dyn CliNpmResolver,
|
||||||
node_resolver: &'a CliNodeResolver,
|
node_resolver: &'a CliNodeResolver,
|
||||||
env_vars: HashMap<String, String>,
|
env_vars: HashMap<String, String>,
|
||||||
|
@ -458,11 +463,11 @@ impl<'a> TaskRunner<'a> {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(npm_resolver) = self.npm_resolver.as_managed() {
|
if let Some(npm_installer) = self.npm_installer {
|
||||||
npm_resolver.ensure_top_level_package_json_install().await?;
|
npm_installer
|
||||||
npm_resolver
|
.ensure_top_level_package_json_install()
|
||||||
.cache_packages(crate::npm::PackageCaching::All)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
npm_installer.cache_packages(PackageCaching::All).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cwd = match &self.task_flags.cwd {
|
let cwd = match &self.task_flags.cwd {
|
||||||
|
@ -497,11 +502,11 @@ impl<'a> TaskRunner<'a> {
|
||||||
argv: &[String],
|
argv: &[String],
|
||||||
) -> Result<i32, deno_core::anyhow::Error> {
|
) -> Result<i32, deno_core::anyhow::Error> {
|
||||||
// ensure the npm packages are installed if using a managed resolver
|
// ensure the npm packages are installed if using a managed resolver
|
||||||
if let Some(npm_resolver) = self.npm_resolver.as_managed() {
|
if let Some(npm_installer) = self.npm_installer {
|
||||||
npm_resolver.ensure_top_level_package_json_install().await?;
|
npm_installer
|
||||||
npm_resolver
|
.ensure_top_level_package_json_install()
|
||||||
.cache_packages(crate::npm::PackageCaching::All)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
npm_installer.cache_packages(PackageCaching::All).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cwd = match &self.task_flags.cwd {
|
let cwd = match &self.task_flags.cwd {
|
||||||
|
|
|
@ -28,6 +28,7 @@ use deno_graph::GraphKind;
|
||||||
use deno_graph::Module;
|
use deno_graph::Module;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_graph::ResolutionResolved;
|
use deno_graph::ResolutionResolved;
|
||||||
|
use deno_resolver::npm::managed::ResolvePkgFolderFromDenoModuleError;
|
||||||
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
|
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use node_resolver::errors::NodeJsErrorCode;
|
use node_resolver::errors::NodeJsErrorCode;
|
||||||
|
@ -709,9 +710,7 @@ pub enum ResolveError {
|
||||||
PackageSubpathResolve(PackageSubpathResolveError),
|
PackageSubpathResolve(PackageSubpathResolveError),
|
||||||
#[class(inherit)]
|
#[class(inherit)]
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
ResolvePkgFolderFromDenoModule(
|
ResolvePkgFolderFromDenoModule(#[from] ResolvePkgFolderFromDenoModuleError),
|
||||||
#[from] crate::npm::ResolvePkgFolderFromDenoModuleError,
|
|
||||||
),
|
|
||||||
#[class(inherit)]
|
#[class(inherit)]
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
ResolveNonGraphSpecifierTypes(#[from] ResolveNonGraphSpecifierTypesError),
|
ResolveNonGraphSpecifierTypes(#[from] ResolveNonGraphSpecifierTypesError),
|
||||||
|
|
|
@ -54,6 +54,8 @@ use crate::args::NpmCachingStrategy;
|
||||||
use crate::args::StorageKeyResolver;
|
use crate::args::StorageKeyResolver;
|
||||||
use crate::node::CliNodeResolver;
|
use crate::node::CliNodeResolver;
|
||||||
use crate::node::CliPackageJsonResolver;
|
use crate::node::CliPackageJsonResolver;
|
||||||
|
use crate::npm::installer::NpmInstaller;
|
||||||
|
use crate::npm::installer::PackageCaching;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
use crate::util::checksum;
|
use crate::util::checksum;
|
||||||
|
@ -148,6 +150,7 @@ struct SharedWorkerState {
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<CliNodeResolver>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
pkg_json_resolver: Arc<CliPackageJsonResolver>,
|
pkg_json_resolver: Arc<CliPackageJsonResolver>,
|
||||||
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
||||||
|
@ -423,6 +426,7 @@ impl CliMainWorkerFactory {
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<CliNodeResolver>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
pkg_json_resolver: Arc<CliPackageJsonResolver>,
|
pkg_json_resolver: Arc<CliPackageJsonResolver>,
|
||||||
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
||||||
|
@ -447,6 +451,7 @@ impl CliMainWorkerFactory {
|
||||||
maybe_lockfile,
|
maybe_lockfile,
|
||||||
module_loader_factory,
|
module_loader_factory,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
|
npm_installer,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
pkg_json_resolver,
|
pkg_json_resolver,
|
||||||
root_cert_store_provider,
|
root_cert_store_provider,
|
||||||
|
@ -496,18 +501,18 @@ impl CliMainWorkerFactory {
|
||||||
let main_module = if let Ok(package_ref) =
|
let main_module = if let Ok(package_ref) =
|
||||||
NpmPackageReqReference::from_specifier(&main_module)
|
NpmPackageReqReference::from_specifier(&main_module)
|
||||||
{
|
{
|
||||||
if let Some(npm_resolver) = shared.npm_resolver.as_managed() {
|
if let Some(npm_installer) = &shared.npm_installer {
|
||||||
let reqs = &[package_ref.req().clone()];
|
let reqs = &[package_ref.req().clone()];
|
||||||
npm_resolver
|
npm_installer
|
||||||
.add_package_reqs(
|
.add_package_reqs(
|
||||||
reqs,
|
reqs,
|
||||||
if matches!(
|
if matches!(
|
||||||
shared.default_npm_caching_strategy,
|
shared.default_npm_caching_strategy,
|
||||||
NpmCachingStrategy::Lazy
|
NpmCachingStrategy::Lazy
|
||||||
) {
|
) {
|
||||||
crate::npm::PackageCaching::Only(reqs.into())
|
PackageCaching::Only(reqs.into())
|
||||||
} else {
|
} else {
|
||||||
crate::npm::PackageCaching::All
|
PackageCaching::All
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
@ -16,7 +16,7 @@ use node_resolver::errors::ReferrerNotFoundError;
|
||||||
use node_resolver::NpmPackageFolderResolver;
|
use node_resolver::NpmPackageFolderResolver;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use super::resolution::NpmResolutionRc;
|
use super::resolution::NpmResolutionCellRc;
|
||||||
use super::NpmCacheDirRc;
|
use super::NpmCacheDirRc;
|
||||||
use super::NpmPackageFsResolver;
|
use super::NpmPackageFsResolver;
|
||||||
use crate::ResolvedNpmRcRc;
|
use crate::ResolvedNpmRcRc;
|
||||||
|
@ -26,14 +26,14 @@ use crate::ResolvedNpmRcRc;
|
||||||
pub struct GlobalNpmPackageResolver {
|
pub struct GlobalNpmPackageResolver {
|
||||||
cache: NpmCacheDirRc,
|
cache: NpmCacheDirRc,
|
||||||
npm_rc: ResolvedNpmRcRc,
|
npm_rc: ResolvedNpmRcRc,
|
||||||
resolution: NpmResolutionRc,
|
resolution: NpmResolutionCellRc,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalNpmPackageResolver {
|
impl GlobalNpmPackageResolver {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cache: NpmCacheDirRc,
|
cache: NpmCacheDirRc,
|
||||||
npm_rc: ResolvedNpmRcRc,
|
npm_rc: ResolvedNpmRcRc,
|
||||||
resolution: NpmResolutionRc,
|
resolution: NpmResolutionCellRc,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cache,
|
cache,
|
||||||
|
|
|
@ -19,7 +19,7 @@ use sys_traits::FsCanonicalize;
|
||||||
use sys_traits::FsMetadata;
|
use sys_traits::FsMetadata;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use super::resolution::NpmResolutionRc;
|
use super::resolution::NpmResolutionCellRc;
|
||||||
use super::NpmPackageFsResolver;
|
use super::NpmPackageFsResolver;
|
||||||
use crate::npm::local::get_package_folder_id_folder_name_from_parts;
|
use crate::npm::local::get_package_folder_id_folder_name_from_parts;
|
||||||
use crate::npm::local::get_package_folder_id_from_folder_name;
|
use crate::npm::local::get_package_folder_id_from_folder_name;
|
||||||
|
@ -32,7 +32,7 @@ use crate::sync::MaybeSync;
|
||||||
pub struct LocalNpmPackageResolver<
|
pub struct LocalNpmPackageResolver<
|
||||||
TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync,
|
TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync,
|
||||||
> {
|
> {
|
||||||
resolution: NpmResolutionRc,
|
resolution: NpmResolutionCellRc,
|
||||||
sys: TSys,
|
sys: TSys,
|
||||||
root_node_modules_path: PathBuf,
|
root_node_modules_path: PathBuf,
|
||||||
root_node_modules_url: Url,
|
root_node_modules_url: Url,
|
||||||
|
@ -43,7 +43,7 @@ impl<TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync>
|
||||||
{
|
{
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
resolution: NpmResolutionRc,
|
resolution: NpmResolutionCellRc,
|
||||||
sys: TSys,
|
sys: TSys,
|
||||||
node_modules_folder: PathBuf,
|
node_modules_folder: PathBuf,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
|
@ -8,10 +8,13 @@ mod resolution;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use deno_npm::resolution::PackageCacheFolderIdNotFoundError;
|
||||||
|
use deno_npm::resolution::PackageNvNotFoundError;
|
||||||
use deno_npm::resolution::PackageReqNotFoundError;
|
use deno_npm::resolution::PackageReqNotFoundError;
|
||||||
use deno_npm::NpmPackageCacheFolderId;
|
use deno_npm::NpmPackageCacheFolderId;
|
||||||
use deno_npm::NpmPackageId;
|
use deno_npm::NpmPackageId;
|
||||||
use deno_path_util::fs::canonicalize_path_maybe_not_exists;
|
use deno_path_util::fs::canonicalize_path_maybe_not_exists;
|
||||||
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use node_resolver::InNpmPackageChecker;
|
use node_resolver::InNpmPackageChecker;
|
||||||
use node_resolver::NpmPackageFolderResolver;
|
use node_resolver::NpmPackageFolderResolver;
|
||||||
|
@ -23,14 +26,24 @@ use self::common::NpmPackageFsResolver;
|
||||||
use self::common::NpmPackageFsResolverRc;
|
use self::common::NpmPackageFsResolverRc;
|
||||||
use self::global::GlobalNpmPackageResolver;
|
use self::global::GlobalNpmPackageResolver;
|
||||||
use self::local::LocalNpmPackageResolver;
|
use self::local::LocalNpmPackageResolver;
|
||||||
pub use self::resolution::NpmResolution;
|
pub use self::resolution::NpmResolutionCell;
|
||||||
pub use self::resolution::NpmResolutionRc;
|
pub use self::resolution::NpmResolutionCellRc;
|
||||||
use crate::sync::new_rc;
|
use crate::sync::new_rc;
|
||||||
use crate::sync::MaybeSend;
|
use crate::sync::MaybeSend;
|
||||||
use crate::sync::MaybeSync;
|
use crate::sync::MaybeSync;
|
||||||
use crate::NpmCacheDirRc;
|
use crate::NpmCacheDirRc;
|
||||||
use crate::ResolvedNpmRcRc;
|
use crate::ResolvedNpmRcRc;
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum ResolvePkgFolderFromDenoModuleError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
PackageNvNotFound(#[from] PackageNvNotFoundError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ResolvePkgFolderFromPkgId(#[from] ResolvePkgFolderFromPkgIdError),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
pub enum ResolvePkgFolderFromPkgIdError {
|
pub enum ResolvePkgFolderFromPkgIdError {
|
||||||
|
@ -66,6 +79,16 @@ pub enum ManagedResolvePkgFolderFromDenoReqError {
|
||||||
ResolvePkgFolderFromPkgId(#[from] ResolvePkgFolderFromPkgIdError),
|
ResolvePkgFolderFromPkgId(#[from] ResolvePkgFolderFromPkgIdError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum ResolvePkgIdFromSpecifierError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
NotFound(#[from] PackageCacheFolderIdNotFoundError),
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::disallowed_types)]
|
#[allow(clippy::disallowed_types)]
|
||||||
pub type ManagedNpmResolverRc<TSys> =
|
pub type ManagedNpmResolverRc<TSys> =
|
||||||
crate::sync::MaybeArc<ManagedNpmResolver<TSys>>;
|
crate::sync::MaybeArc<ManagedNpmResolver<TSys>>;
|
||||||
|
@ -73,7 +96,7 @@ pub type ManagedNpmResolverRc<TSys> =
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ManagedNpmResolver<TSys: FsCanonicalize> {
|
pub struct ManagedNpmResolver<TSys: FsCanonicalize> {
|
||||||
fs_resolver: NpmPackageFsResolverRc,
|
fs_resolver: NpmPackageFsResolverRc,
|
||||||
resolution: NpmResolutionRc,
|
resolution: NpmResolutionCellRc,
|
||||||
sys: TSys,
|
sys: TSys,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +112,7 @@ impl<TSys: FsCanonicalize> ManagedNpmResolver<TSys> {
|
||||||
>(
|
>(
|
||||||
npm_cache_dir: &NpmCacheDirRc,
|
npm_cache_dir: &NpmCacheDirRc,
|
||||||
npm_rc: &ResolvedNpmRcRc,
|
npm_rc: &ResolvedNpmRcRc,
|
||||||
resolution: NpmResolutionRc,
|
resolution: NpmResolutionCellRc,
|
||||||
sys: TCreateSys,
|
sys: TCreateSys,
|
||||||
maybe_node_modules_path: Option<PathBuf>,
|
maybe_node_modules_path: Option<PathBuf>,
|
||||||
) -> ManagedNpmResolver<TCreateSys> {
|
) -> ManagedNpmResolver<TCreateSys> {
|
||||||
|
@ -144,6 +167,14 @@ impl<TSys: FsCanonicalize> ManagedNpmResolver<TSys> {
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_pkg_folder_from_deno_module(
|
||||||
|
&self,
|
||||||
|
nv: &PackageNv,
|
||||||
|
) -> Result<PathBuf, ResolvePkgFolderFromDenoModuleError> {
|
||||||
|
let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(nv)?;
|
||||||
|
Ok(self.resolve_pkg_folder_from_pkg_id(&pkg_id)?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolve_pkg_folder_from_deno_module_req(
|
pub fn resolve_pkg_folder_from_deno_module_req(
|
||||||
&self,
|
&self,
|
||||||
req: &PackageReq,
|
req: &PackageReq,
|
||||||
|
@ -162,6 +193,24 @@ impl<TSys: FsCanonicalize> ManagedNpmResolver<TSys> {
|
||||||
.fs_resolver
|
.fs_resolver
|
||||||
.resolve_package_cache_folder_id_from_specifier(specifier)
|
.resolve_package_cache_folder_id_from_specifier(specifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves the package id from the provided specifier.
|
||||||
|
pub fn resolve_pkg_id_from_specifier(
|
||||||
|
&self,
|
||||||
|
specifier: &Url,
|
||||||
|
) -> Result<Option<NpmPackageId>, ResolvePkgIdFromSpecifierError> {
|
||||||
|
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)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TSys: FsCanonicalize + std::fmt::Debug + MaybeSend + MaybeSync>
|
impl<TSys: FsCanonicalize + std::fmt::Debug + MaybeSend + MaybeSync>
|
||||||
|
|
|
@ -18,16 +18,17 @@ use deno_semver::package::PackageReq;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
#[allow(clippy::disallowed_types)]
|
#[allow(clippy::disallowed_types)]
|
||||||
pub type NpmResolutionRc = crate::sync::MaybeArc<NpmResolution>;
|
pub type NpmResolutionCellRc = crate::sync::MaybeArc<NpmResolutionCell>;
|
||||||
|
|
||||||
/// Handles updating and storing npm resolution in memory.
|
/// Handles updating and storing npm resolution in memory.
|
||||||
///
|
///
|
||||||
/// This does not interact with the file system.
|
/// This does not interact with the file system.
|
||||||
pub struct NpmResolution {
|
#[derive(Default)]
|
||||||
|
pub struct NpmResolutionCell {
|
||||||
snapshot: RwLock<NpmResolutionSnapshot>,
|
snapshot: RwLock<NpmResolutionSnapshot>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for NpmResolution {
|
impl std::fmt::Debug for NpmResolutionCell {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let snapshot = self.snapshot.read();
|
let snapshot = self.snapshot.read();
|
||||||
f.debug_struct("NpmResolution")
|
f.debug_struct("NpmResolution")
|
||||||
|
@ -36,7 +37,7 @@ impl std::fmt::Debug for NpmResolution {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NpmResolution {
|
impl NpmResolutionCell {
|
||||||
pub fn from_serialized(
|
pub fn from_serialized(
|
||||||
initial_snapshot: Option<ValidSerializedNpmResolutionSnapshot>,
|
initial_snapshot: Option<ValidSerializedNpmResolutionSnapshot>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
|
@ -140,7 +140,9 @@ pub trait NpmProcessStateProvider:
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EmptyNpmProcessStateProvider;
|
pub struct EmptyNpmProcessStateProvider;
|
||||||
|
|
||||||
impl NpmProcessStateProvider for EmptyNpmProcessStateProvider {}
|
impl NpmProcessStateProvider for EmptyNpmProcessStateProvider {}
|
||||||
|
|
||||||
deno_core::extension!(
|
deno_core::extension!(
|
||||||
deno_process,
|
deno_process,
|
||||||
ops = [
|
ops = [
|
||||||
|
|
Loading…
Add table
Reference in a new issue