mirror of
https://github.com/denoland/deno.git
synced 2025-02-01 20:25:12 -05:00
fix(npm): cache bust npm specifiers more aggressively (#18636)
Part 1: #18622 Part 2: This PR Closes #16901 --------- Co-authored-by: Luca Casonato <hello@lcas.dev>
This commit is contained in:
parent
b183737fc9
commit
4fab252153
14 changed files with 289 additions and 143 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -935,9 +935,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_doc"
|
name = "deno_doc"
|
||||||
version = "0.60.0"
|
version = "0.61.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "029ec20ba7a3c9d55597db7afa20576367ea8d70371a97b84f9909014cfe110f"
|
checksum = "ae1ba6a3137da0ed19838c09c6fb9c7a07af642786b298fc29e088cc5643e729"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"deno_ast",
|
"deno_ast",
|
||||||
|
@ -953,9 +953,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_emit"
|
name = "deno_emit"
|
||||||
version = "0.18.0"
|
version = "0.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8004481b057addda0779edd5adb47e5ac9db7ae431c879300d22d535cc83cfae"
|
checksum = "c01676751a0ee50ebad80734735f9a28c6eabb164050034e10956b72af563941"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
|
@ -1017,9 +1017,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_graph"
|
name = "deno_graph"
|
||||||
version = "0.46.0"
|
version = "0.47.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fb5531f3c2be6926e51ce5888fcffa434ca83516c53d26563882533aee871d0"
|
checksum = "3e81896f3abfe0c6410518cc0285155e6faa2aa87ca8da32fbf1670ef1254ea2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"data-url",
|
"data-url",
|
||||||
|
@ -1734,9 +1734,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "eszip"
|
name = "eszip"
|
||||||
version = "0.39.0"
|
version = "0.40.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "207f6568e7dde0c18eb306af104c4e7fe91f77eb99afeffd13f9c7735de4bb4d"
|
checksum = "5a0a0addd73b5077a769e23a914a68ec8862c310b6127e8383505f676684f65c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.0",
|
"base64 0.21.0",
|
||||||
|
|
|
@ -42,9 +42,9 @@ winres.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
|
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
|
||||||
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||||
deno_doc = "0.60.0"
|
deno_doc = "0.61.0"
|
||||||
deno_emit = "0.18.0"
|
deno_emit = "0.19.0"
|
||||||
deno_graph = "=0.46.0"
|
deno_graph = "=0.47.1"
|
||||||
deno_lint = { version = "0.43.0", features = ["docs"] }
|
deno_lint = { version = "0.43.0", features = ["docs"] }
|
||||||
deno_lockfile.workspace = true
|
deno_lockfile.workspace = true
|
||||||
deno_npm = "0.2.0"
|
deno_npm = "0.2.0"
|
||||||
|
@ -70,7 +70,7 @@ dprint-plugin-markdown = "=0.15.2"
|
||||||
dprint-plugin-typescript = "=0.84.0"
|
dprint-plugin-typescript = "=0.84.0"
|
||||||
encoding_rs.workspace = true
|
encoding_rs.workspace = true
|
||||||
env_logger = "=0.9.0"
|
env_logger = "=0.9.0"
|
||||||
eszip = "=0.39.0"
|
eszip = "=0.40.0"
|
||||||
fancy-regex = "=0.10.0"
|
fancy-regex = "=0.10.0"
|
||||||
flate2.workspace = true
|
flate2.workspace = true
|
||||||
fs3.workspace = true
|
fs3.workspace = true
|
||||||
|
|
|
@ -64,8 +64,8 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use crate::cache::DenoDir;
|
use crate::cache::DenoDir;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::FileFetcher;
|
||||||
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::NpmProcessState;
|
use crate::npm::NpmProcessState;
|
||||||
use crate::npm::NpmRegistry;
|
|
||||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||||
use crate::version;
|
use crate::version;
|
||||||
|
|
||||||
|
@ -744,7 +744,7 @@ impl CliOptions {
|
||||||
|
|
||||||
pub async fn resolve_npm_resolution_snapshot(
|
pub async fn resolve_npm_resolution_snapshot(
|
||||||
&self,
|
&self,
|
||||||
api: &NpmRegistry,
|
api: &CliNpmRegistryApi,
|
||||||
) -> Result<Option<NpmResolutionSnapshot>, AnyError> {
|
) -> Result<Option<NpmResolutionSnapshot>, AnyError> {
|
||||||
if let Some(state) = &*NPM_PROCESS_STATE {
|
if let Some(state) = &*NPM_PROCESS_STATE {
|
||||||
// TODO(bartlomieju): remove this clone
|
// TODO(bartlomieju): remove this clone
|
||||||
|
|
|
@ -20,8 +20,8 @@ use crate::lsp::logging::lsp_warn;
|
||||||
use crate::node;
|
use crate::node;
|
||||||
use crate::node::node_resolve_npm_reference;
|
use crate::node::node_resolve_npm_reference;
|
||||||
use crate::node::NodeResolution;
|
use crate::node::NodeResolution;
|
||||||
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::NpmPackageResolver;
|
use crate::npm::NpmPackageResolver;
|
||||||
use crate::npm::NpmRegistry;
|
|
||||||
use crate::npm::NpmResolution;
|
use crate::npm::NpmResolution;
|
||||||
use crate::npm::PackageJsonDepsInstaller;
|
use crate::npm::PackageJsonDepsInstaller;
|
||||||
use crate::resolver::CliGraphResolver;
|
use crate::resolver::CliGraphResolver;
|
||||||
|
@ -1166,7 +1166,7 @@ impl Documents {
|
||||||
maybe_import_map: Option<Arc<import_map::ImportMap>>,
|
maybe_import_map: Option<Arc<import_map::ImportMap>>,
|
||||||
maybe_config_file: Option<&ConfigFile>,
|
maybe_config_file: Option<&ConfigFile>,
|
||||||
maybe_package_json: Option<&PackageJson>,
|
maybe_package_json: Option<&PackageJson>,
|
||||||
npm_registry_api: NpmRegistry,
|
npm_registry_api: CliNpmRegistryApi,
|
||||||
npm_resolution: NpmResolution,
|
npm_resolution: NpmResolution,
|
||||||
) {
|
) {
|
||||||
fn calculate_resolver_config_hash(
|
fn calculate_resolver_config_hash(
|
||||||
|
@ -1864,7 +1864,7 @@ console.log(b, "hello deno");
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_documents_refresh_dependencies_config_change() {
|
fn test_documents_refresh_dependencies_config_change() {
|
||||||
let npm_registry_api = NpmRegistry::new_uninitialized();
|
let npm_registry_api = CliNpmRegistryApi::new_uninitialized();
|
||||||
let npm_resolution =
|
let npm_resolution =
|
||||||
NpmResolution::new(npm_registry_api.clone(), None, None);
|
NpmResolution::new(npm_registry_api.clone(), None, None);
|
||||||
|
|
||||||
|
|
|
@ -79,9 +79,9 @@ use crate::graph_util;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
use crate::lsp::urls::LspUrlKind;
|
use crate::lsp::urls::LspUrlKind;
|
||||||
use crate::npm::create_npm_fs_resolver;
|
use crate::npm::create_npm_fs_resolver;
|
||||||
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::NpmCache;
|
use crate::npm::NpmCache;
|
||||||
use crate::npm::NpmPackageResolver;
|
use crate::npm::NpmPackageResolver;
|
||||||
use crate::npm::NpmRegistry;
|
|
||||||
use crate::npm::NpmResolution;
|
use crate::npm::NpmResolution;
|
||||||
use crate::proc_state::ProcState;
|
use crate::proc_state::ProcState;
|
||||||
use crate::tools::fmt::format_file;
|
use crate::tools::fmt::format_file;
|
||||||
|
@ -145,7 +145,7 @@ pub struct Inner {
|
||||||
/// A lazily create "server" for handling test run requests.
|
/// A lazily create "server" for handling test run requests.
|
||||||
maybe_testing_server: Option<testing::TestServer>,
|
maybe_testing_server: Option<testing::TestServer>,
|
||||||
/// Npm's registry api.
|
/// Npm's registry api.
|
||||||
npm_api: NpmRegistry,
|
npm_api: CliNpmRegistryApi,
|
||||||
/// Npm cache
|
/// Npm cache
|
||||||
npm_cache: NpmCache,
|
npm_cache: NpmCache,
|
||||||
/// Npm resolution that is stored in memory.
|
/// Npm resolution that is stored in memory.
|
||||||
|
@ -417,8 +417,13 @@ impl LanguageServer {
|
||||||
fn create_lsp_structs(
|
fn create_lsp_structs(
|
||||||
dir: &DenoDir,
|
dir: &DenoDir,
|
||||||
http_client: HttpClient,
|
http_client: HttpClient,
|
||||||
) -> (NpmRegistry, NpmCache, NpmPackageResolver, NpmResolution) {
|
) -> (
|
||||||
let registry_url = NpmRegistry::default_url();
|
CliNpmRegistryApi,
|
||||||
|
NpmCache,
|
||||||
|
NpmPackageResolver,
|
||||||
|
NpmResolution,
|
||||||
|
) {
|
||||||
|
let registry_url = CliNpmRegistryApi::default_url();
|
||||||
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
|
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
|
||||||
let npm_cache = NpmCache::from_deno_dir(
|
let npm_cache = NpmCache::from_deno_dir(
|
||||||
dir,
|
dir,
|
||||||
|
@ -430,7 +435,7 @@ fn create_lsp_structs(
|
||||||
http_client.clone(),
|
http_client.clone(),
|
||||||
progress_bar.clone(),
|
progress_bar.clone(),
|
||||||
);
|
);
|
||||||
let api = NpmRegistry::new(
|
let api = CliNpmRegistryApi::new(
|
||||||
registry_url.clone(),
|
registry_url.clone(),
|
||||||
npm_cache.clone(),
|
npm_cache.clone(),
|
||||||
http_client,
|
http_client,
|
||||||
|
|
|
@ -1,33 +1,69 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures::stream::FuturesOrdered;
|
use deno_core::futures::stream::FuturesOrdered;
|
||||||
use deno_core::futures::StreamExt;
|
use deno_core::futures::StreamExt;
|
||||||
use deno_npm::registry::NpmRegistryApi;
|
use deno_npm::registry::NpmRegistryApi;
|
||||||
|
use deno_npm::registry::NpmRegistryPackageInfoLoadError;
|
||||||
|
use deno_semver::npm::NpmPackageReq;
|
||||||
|
|
||||||
use crate::args::package_json::PackageJsonDeps;
|
use crate::args::package_json::PackageJsonDeps;
|
||||||
use crate::util::sync::AtomicFlag;
|
use crate::util::sync::AtomicFlag;
|
||||||
|
|
||||||
use super::NpmRegistry;
|
use super::CliNpmRegistryApi;
|
||||||
use super::NpmResolution;
|
use super::NpmResolution;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct PackageJsonDepsInstallerInner {
|
struct PackageJsonDepsInstallerInner {
|
||||||
has_installed_flag: AtomicFlag,
|
has_installed_flag: AtomicFlag,
|
||||||
npm_registry_api: NpmRegistry,
|
npm_registry_api: CliNpmRegistryApi,
|
||||||
npm_resolution: NpmResolution,
|
npm_resolution: NpmResolution,
|
||||||
package_deps: PackageJsonDeps,
|
package_deps: PackageJsonDeps,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PackageJsonDepsInstallerInner {
|
||||||
|
pub fn reqs(&self) -> Vec<&NpmPackageReq> {
|
||||||
|
let mut package_reqs = self
|
||||||
|
.package_deps
|
||||||
|
.values()
|
||||||
|
.filter_map(|r| r.as_ref().ok())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
package_reqs.sort(); // deterministic resolution
|
||||||
|
package_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reqs_with_info_futures(
|
||||||
|
&self,
|
||||||
|
) -> FuturesOrdered<
|
||||||
|
impl Future<
|
||||||
|
Output = Result<
|
||||||
|
(&NpmPackageReq, Arc<deno_npm::registry::NpmPackageInfo>),
|
||||||
|
NpmRegistryPackageInfoLoadError,
|
||||||
|
>,
|
||||||
|
>,
|
||||||
|
> {
|
||||||
|
let package_reqs = self.reqs();
|
||||||
|
|
||||||
|
FuturesOrdered::from_iter(package_reqs.into_iter().map(|req| {
|
||||||
|
let api = self.npm_registry_api.clone();
|
||||||
|
async move {
|
||||||
|
let info = api.package_info(&req.name).await?;
|
||||||
|
Ok::<_, NpmRegistryPackageInfoLoadError>((req, info))
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Holds and controls installing dependencies from package.json.
|
/// Holds and controls installing dependencies from package.json.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct PackageJsonDepsInstaller(Option<Arc<PackageJsonDepsInstallerInner>>);
|
pub struct PackageJsonDepsInstaller(Option<Arc<PackageJsonDepsInstallerInner>>);
|
||||||
|
|
||||||
impl PackageJsonDepsInstaller {
|
impl PackageJsonDepsInstaller {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
npm_registry_api: NpmRegistry,
|
npm_registry_api: CliNpmRegistryApi,
|
||||||
npm_resolution: NpmResolution,
|
npm_resolution: NpmResolution,
|
||||||
deps: Option<PackageJsonDeps>,
|
deps: Option<PackageJsonDeps>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -57,27 +93,23 @@ impl PackageJsonDepsInstaller {
|
||||||
return Ok(()); // already installed by something else
|
return Ok(()); // already installed by something else
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut package_reqs = inner
|
let mut reqs_with_info_futures = inner.reqs_with_info_futures();
|
||||||
.package_deps
|
|
||||||
.values()
|
|
||||||
.filter_map(|r| r.as_ref().ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
package_reqs.sort(); // deterministic resolution
|
|
||||||
|
|
||||||
let mut req_with_infos =
|
while let Some(result) = reqs_with_info_futures.next().await {
|
||||||
FuturesOrdered::from_iter(package_reqs.into_iter().map(|req| {
|
|
||||||
let api = inner.npm_registry_api.clone();
|
|
||||||
async move {
|
|
||||||
let info = api.package_info(&req.name).await?;
|
|
||||||
Ok::<_, AnyError>((req, info))
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
while let Some(result) = req_with_infos.next().await {
|
|
||||||
let (req, info) = result?;
|
let (req, info) = result?;
|
||||||
inner
|
let result = inner
|
||||||
.npm_resolution
|
.npm_resolution
|
||||||
.resolve_package_req_as_pending_with_info(req, &info)?;
|
.resolve_package_req_as_pending_with_info(req, &info);
|
||||||
|
if let Err(err) = result {
|
||||||
|
if inner.npm_registry_api.mark_force_reload() {
|
||||||
|
log::debug!("Failed to resolve package. Retrying. Error: {err:#}");
|
||||||
|
// re-initialize
|
||||||
|
inner.npm_registry_api.clear_memory_cache();
|
||||||
|
reqs_with_info_futures = inner.reqs_with_info_futures();
|
||||||
|
} else {
|
||||||
|
return Err(err.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -10,7 +10,7 @@ mod tarball;
|
||||||
pub use cache::should_sync_download;
|
pub use cache::should_sync_download;
|
||||||
pub use cache::NpmCache;
|
pub use cache::NpmCache;
|
||||||
pub use installer::PackageJsonDepsInstaller;
|
pub use installer::PackageJsonDepsInstaller;
|
||||||
pub use registry::NpmRegistry;
|
pub use registry::CliNpmRegistryApi;
|
||||||
pub use resolution::NpmResolution;
|
pub use resolution::NpmResolution;
|
||||||
pub use resolvers::create_npm_fs_resolver;
|
pub use resolvers::create_npm_fs_resolver;
|
||||||
pub use resolvers::NpmPackageResolver;
|
pub use resolvers::NpmPackageResolver;
|
||||||
|
|
|
@ -53,9 +53,9 @@ static NPM_REGISTRY_DEFAULT_URL: Lazy<Url> = Lazy::new(|| {
|
||||||
});
|
});
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NpmRegistry(Option<Arc<NpmRegistryApiInner>>);
|
pub struct CliNpmRegistryApi(Option<Arc<CliNpmRegistryApiInner>>);
|
||||||
|
|
||||||
impl NpmRegistry {
|
impl CliNpmRegistryApi {
|
||||||
pub fn default_url() -> &'static Url {
|
pub fn default_url() -> &'static Url {
|
||||||
&NPM_REGISTRY_DEFAULT_URL
|
&NPM_REGISTRY_DEFAULT_URL
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ impl NpmRegistry {
|
||||||
http_client: HttpClient,
|
http_client: HttpClient,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self(Some(Arc::new(NpmRegistryApiInner {
|
Self(Some(Arc::new(CliNpmRegistryApiInner {
|
||||||
base_url,
|
base_url,
|
||||||
cache,
|
cache,
|
||||||
force_reload_flag: Default::default(),
|
force_reload_flag: Default::default(),
|
||||||
|
@ -104,14 +104,18 @@ impl NpmRegistry {
|
||||||
///
|
///
|
||||||
/// Returns true if it was successfully set for the first time.
|
/// Returns true if it was successfully set for the first time.
|
||||||
pub fn mark_force_reload(&self) -> bool {
|
pub fn mark_force_reload(&self) -> bool {
|
||||||
// never force reload the registry information if reloading is disabled
|
// never force reload the registry information if reloading
|
||||||
if matches!(self.inner().cache.cache_setting(), CacheSetting::Only) {
|
// is disabled or if we're already reloading
|
||||||
|
if matches!(
|
||||||
|
self.inner().cache.cache_setting(),
|
||||||
|
CacheSetting::Only | CacheSetting::ReloadAll
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
self.inner().force_reload_flag.raise()
|
self.inner().force_reload_flag.raise()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner(&self) -> &Arc<NpmRegistryApiInner> {
|
fn inner(&self) -> &Arc<CliNpmRegistryApiInner> {
|
||||||
// this panicking indicates a bug in the code where this
|
// this panicking indicates a bug in the code where this
|
||||||
// wasn't initialized
|
// wasn't initialized
|
||||||
self.0.as_ref().unwrap()
|
self.0.as_ref().unwrap()
|
||||||
|
@ -122,7 +126,7 @@ static SYNC_DOWNLOAD_TASK_QUEUE: Lazy<TaskQueue> =
|
||||||
Lazy::new(TaskQueue::default);
|
Lazy::new(TaskQueue::default);
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl NpmRegistryApi for NpmRegistry {
|
impl NpmRegistryApi for CliNpmRegistryApi {
|
||||||
async fn package_info(
|
async fn package_info(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -147,16 +151,17 @@ impl NpmRegistryApi for NpmRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CacheItemPendingResult =
|
||||||
|
Result<Option<Arc<NpmPackageInfo>>, Arc<AnyError>>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum CacheItem {
|
enum CacheItem {
|
||||||
Pending(
|
Pending(Shared<BoxFuture<'static, CacheItemPendingResult>>),
|
||||||
Shared<BoxFuture<'static, Result<Option<Arc<NpmPackageInfo>>, String>>>,
|
|
||||||
),
|
|
||||||
Resolved(Option<Arc<NpmPackageInfo>>),
|
Resolved(Option<Arc<NpmPackageInfo>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct NpmRegistryApiInner {
|
struct CliNpmRegistryApiInner {
|
||||||
base_url: Url,
|
base_url: Url,
|
||||||
cache: NpmCache,
|
cache: NpmCache,
|
||||||
force_reload_flag: AtomicFlag,
|
force_reload_flag: AtomicFlag,
|
||||||
|
@ -166,7 +171,7 @@ struct NpmRegistryApiInner {
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NpmRegistryApiInner {
|
impl CliNpmRegistryApiInner {
|
||||||
pub async fn maybe_package_info(
|
pub async fn maybe_package_info(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -196,9 +201,15 @@ impl NpmRegistryApiInner {
|
||||||
let future = {
|
let future = {
|
||||||
let api = self.clone();
|
let api = self.clone();
|
||||||
let name = name.to_string();
|
let name = name.to_string();
|
||||||
async move { api.load_package_info_from_registry(&name).await }
|
async move {
|
||||||
.boxed()
|
api
|
||||||
.shared()
|
.load_package_info_from_registry(&name)
|
||||||
|
.await
|
||||||
|
.map(|info| info.map(Arc::new))
|
||||||
|
.map_err(Arc::new)
|
||||||
|
}
|
||||||
|
.boxed()
|
||||||
|
.shared()
|
||||||
};
|
};
|
||||||
mem_cache
|
mem_cache
|
||||||
.insert(name.to_string(), CacheItem::Pending(future.clone()));
|
.insert(name.to_string(), CacheItem::Pending(future.clone()));
|
||||||
|
@ -220,11 +231,11 @@ impl NpmRegistryApiInner {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// purge the item from the cache so it loads next time
|
// purge the item from the cache so it loads next time
|
||||||
self.mem_cache.lock().remove(name);
|
self.mem_cache.lock().remove(name);
|
||||||
Err(anyhow!("{}", err))
|
Err(anyhow!("{:#}", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(future.await.map_err(|err| anyhow!("{}", err))?)
|
Ok(future.await.map_err(|err| anyhow!("{:#}", err))?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +314,7 @@ impl NpmRegistryApiInner {
|
||||||
async fn load_package_info_from_registry(
|
async fn load_package_info_from_registry(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Result<Option<Arc<NpmPackageInfo>>, String> {
|
) -> Result<Option<NpmPackageInfo>, AnyError> {
|
||||||
self
|
self
|
||||||
.load_package_info_from_registry_inner(name)
|
.load_package_info_from_registry_inner(name)
|
||||||
.await
|
.await
|
||||||
|
@ -314,9 +325,6 @@ impl NpmRegistryApiInner {
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(|info| info.map(Arc::new))
|
|
||||||
// make cloneable
|
|
||||||
.map_err(|err| format!("{err:#}"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_package_info_from_registry_inner(
|
async fn load_package_info_from_registry_inner(
|
||||||
|
|
|
@ -27,7 +27,7 @@ use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
|
||||||
use crate::args::Lockfile;
|
use crate::args::Lockfile;
|
||||||
|
|
||||||
use super::registry::NpmRegistry;
|
use super::registry::CliNpmRegistryApi;
|
||||||
|
|
||||||
/// Handles updating and storing npm resolution in memory where the underlying
|
/// Handles updating and storing npm resolution in memory where the underlying
|
||||||
/// snapshot can be updated concurrently. Additionally handles updating the lockfile
|
/// snapshot can be updated concurrently. Additionally handles updating the lockfile
|
||||||
|
@ -38,7 +38,7 @@ use super::registry::NpmRegistry;
|
||||||
pub struct NpmResolution(Arc<NpmResolutionInner>);
|
pub struct NpmResolution(Arc<NpmResolutionInner>);
|
||||||
|
|
||||||
struct NpmResolutionInner {
|
struct NpmResolutionInner {
|
||||||
api: NpmRegistry,
|
api: CliNpmRegistryApi,
|
||||||
snapshot: RwLock<NpmResolutionSnapshot>,
|
snapshot: RwLock<NpmResolutionSnapshot>,
|
||||||
update_queue: TaskQueue,
|
update_queue: TaskQueue,
|
||||||
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
|
@ -55,7 +55,7 @@ impl std::fmt::Debug for NpmResolution {
|
||||||
|
|
||||||
impl NpmResolution {
|
impl NpmResolution {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
api: NpmRegistry,
|
api: CliNpmRegistryApi,
|
||||||
initial_snapshot: Option<NpmResolutionSnapshot>,
|
initial_snapshot: Option<NpmResolutionSnapshot>,
|
||||||
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -247,7 +247,7 @@ impl NpmResolution {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_package_reqs_to_snapshot(
|
async fn add_package_reqs_to_snapshot(
|
||||||
api: &NpmRegistry,
|
api: &CliNpmRegistryApi,
|
||||||
// todo(18079): it should be possible to pass &[NpmPackageReq] in here
|
// todo(18079): it should be possible to pass &[NpmPackageReq] in here
|
||||||
// and avoid all these clones, but the LSP complains because of its
|
// and avoid all these clones, but the LSP complains because of its
|
||||||
// `Send` requirement
|
// `Send` requirement
|
||||||
|
|
|
@ -26,9 +26,9 @@ use crate::http_util::HttpClient;
|
||||||
use crate::node;
|
use crate::node;
|
||||||
use crate::node::NodeResolution;
|
use crate::node::NodeResolution;
|
||||||
use crate::npm::create_npm_fs_resolver;
|
use crate::npm::create_npm_fs_resolver;
|
||||||
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::NpmCache;
|
use crate::npm::NpmCache;
|
||||||
use crate::npm::NpmPackageResolver;
|
use crate::npm::NpmPackageResolver;
|
||||||
use crate::npm::NpmRegistry;
|
|
||||||
use crate::npm::NpmResolution;
|
use crate::npm::NpmResolution;
|
||||||
use crate::npm::PackageJsonDepsInstaller;
|
use crate::npm::PackageJsonDepsInstaller;
|
||||||
use crate::resolver::CliGraphResolver;
|
use crate::resolver::CliGraphResolver;
|
||||||
|
@ -95,7 +95,7 @@ pub struct Inner {
|
||||||
pub resolver: Arc<CliGraphResolver>,
|
pub resolver: Arc<CliGraphResolver>,
|
||||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||||
pub node_analysis_cache: NodeAnalysisCache,
|
pub node_analysis_cache: NodeAnalysisCache,
|
||||||
pub npm_api: NpmRegistry,
|
pub npm_api: CliNpmRegistryApi,
|
||||||
pub npm_cache: NpmCache,
|
pub npm_cache: NpmCache,
|
||||||
pub npm_resolver: NpmPackageResolver,
|
pub npm_resolver: NpmPackageResolver,
|
||||||
pub npm_resolution: NpmResolution,
|
pub npm_resolution: NpmResolution,
|
||||||
|
@ -233,14 +233,14 @@ impl ProcState {
|
||||||
|
|
||||||
let lockfile = cli_options.maybe_lock_file();
|
let lockfile = cli_options.maybe_lock_file();
|
||||||
|
|
||||||
let npm_registry_url = NpmRegistry::default_url().to_owned();
|
let npm_registry_url = CliNpmRegistryApi::default_url().to_owned();
|
||||||
let npm_cache = NpmCache::from_deno_dir(
|
let npm_cache = NpmCache::from_deno_dir(
|
||||||
&dir,
|
&dir,
|
||||||
cli_options.cache_setting(),
|
cli_options.cache_setting(),
|
||||||
http_client.clone(),
|
http_client.clone(),
|
||||||
progress_bar.clone(),
|
progress_bar.clone(),
|
||||||
);
|
);
|
||||||
let npm_api = NpmRegistry::new(
|
let npm_api = CliNpmRegistryApi::new(
|
||||||
npm_registry_url.clone(),
|
npm_registry_url.clone(),
|
||||||
npm_cache.clone(),
|
npm_cache.clone(),
|
||||||
http_client.clone(),
|
http_client.clone(),
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::anyhow::bail;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures::future;
|
use deno_core::futures::future;
|
||||||
use deno_core::futures::future::LocalBoxFuture;
|
use deno_core::futures::future::LocalBoxFuture;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_core::TaskQueue;
|
use deno_core::TaskQueue;
|
||||||
|
use deno_graph::source::NpmPackageReqResolution;
|
||||||
use deno_graph::source::NpmResolver;
|
use deno_graph::source::NpmResolver;
|
||||||
use deno_graph::source::Resolver;
|
use deno_graph::source::Resolver;
|
||||||
use deno_graph::source::UnknownBuiltInNodeModuleError;
|
use deno_graph::source::UnknownBuiltInNodeModuleError;
|
||||||
use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE;
|
use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE;
|
||||||
use deno_npm::registry::NpmRegistryApi;
|
use deno_npm::registry::NpmRegistryApi;
|
||||||
use deno_runtime::deno_node::is_builtin_node_module;
|
use deno_runtime::deno_node::is_builtin_node_module;
|
||||||
use deno_semver::npm::NpmPackageNv;
|
|
||||||
use deno_semver::npm::NpmPackageReq;
|
use deno_semver::npm::NpmPackageReq;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::args::package_json::PackageJsonDeps;
|
use crate::args::package_json::PackageJsonDeps;
|
||||||
use crate::args::JsxImportSourceConfig;
|
use crate::args::JsxImportSourceConfig;
|
||||||
use crate::npm::NpmRegistry;
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::NpmResolution;
|
use crate::npm::NpmResolution;
|
||||||
use crate::npm::PackageJsonDepsInstaller;
|
use crate::npm::PackageJsonDepsInstaller;
|
||||||
use crate::util::sync::AtomicFlag;
|
use crate::util::sync::AtomicFlag;
|
||||||
|
@ -34,7 +33,7 @@ pub struct CliGraphResolver {
|
||||||
maybe_default_jsx_import_source: Option<String>,
|
maybe_default_jsx_import_source: Option<String>,
|
||||||
maybe_jsx_import_source_module: Option<String>,
|
maybe_jsx_import_source_module: Option<String>,
|
||||||
no_npm: bool,
|
no_npm: bool,
|
||||||
npm_registry_api: NpmRegistry,
|
npm_registry_api: CliNpmRegistryApi,
|
||||||
npm_resolution: NpmResolution,
|
npm_resolution: NpmResolution,
|
||||||
package_json_deps_installer: PackageJsonDepsInstaller,
|
package_json_deps_installer: PackageJsonDepsInstaller,
|
||||||
found_package_json_dep_flag: Arc<AtomicFlag>,
|
found_package_json_dep_flag: Arc<AtomicFlag>,
|
||||||
|
@ -45,7 +44,7 @@ impl Default for CliGraphResolver {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
// This is not ideal, but necessary for the LSP. In the future, we should
|
// This is not ideal, but necessary for the LSP. In the future, we should
|
||||||
// refactor the LSP and force this to be initialized.
|
// refactor the LSP and force this to be initialized.
|
||||||
let npm_registry_api = NpmRegistry::new_uninitialized();
|
let npm_registry_api = CliNpmRegistryApi::new_uninitialized();
|
||||||
let npm_resolution =
|
let npm_resolution =
|
||||||
NpmResolution::new(npm_registry_api.clone(), None, None);
|
NpmResolution::new(npm_registry_api.clone(), None, None);
|
||||||
Self {
|
Self {
|
||||||
|
@ -67,7 +66,7 @@ impl CliGraphResolver {
|
||||||
maybe_jsx_import_source_config: Option<JsxImportSourceConfig>,
|
maybe_jsx_import_source_config: Option<JsxImportSourceConfig>,
|
||||||
maybe_import_map: Option<Arc<ImportMap>>,
|
maybe_import_map: Option<Arc<ImportMap>>,
|
||||||
no_npm: bool,
|
no_npm: bool,
|
||||||
npm_registry_api: NpmRegistry,
|
npm_registry_api: CliNpmRegistryApi,
|
||||||
npm_resolution: NpmResolution,
|
npm_resolution: NpmResolution,
|
||||||
package_json_deps_installer: PackageJsonDepsInstaller,
|
package_json_deps_installer: PackageJsonDepsInstaller,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -204,7 +203,7 @@ impl NpmResolver for CliGraphResolver {
|
||||||
fn load_and_cache_npm_package_info(
|
fn load_and_cache_npm_package_info(
|
||||||
&self,
|
&self,
|
||||||
package_name: &str,
|
package_name: &str,
|
||||||
) -> LocalBoxFuture<'static, Result<(), String>> {
|
) -> LocalBoxFuture<'static, Result<(), AnyError>> {
|
||||||
if self.no_npm {
|
if self.no_npm {
|
||||||
// return it succeeded and error at the import site below
|
// return it succeeded and error at the import site below
|
||||||
return Box::pin(future::ready(Ok(())));
|
return Box::pin(future::ready(Ok(())));
|
||||||
|
@ -224,7 +223,7 @@ impl NpmResolver for CliGraphResolver {
|
||||||
.package_info(&package_name)
|
.package_info(&package_name)
|
||||||
.await
|
.await
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|err| format!("{err:#}"));
|
.map_err(|err| err.into());
|
||||||
drop(permit);
|
drop(permit);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -234,17 +233,26 @@ impl NpmResolver for CliGraphResolver {
|
||||||
fn resolve_npm(
|
fn resolve_npm(
|
||||||
&self,
|
&self,
|
||||||
package_req: &NpmPackageReq,
|
package_req: &NpmPackageReq,
|
||||||
) -> Result<NpmPackageNv, AnyError> {
|
) -> NpmPackageReqResolution {
|
||||||
if self.no_npm {
|
if self.no_npm {
|
||||||
bail!("npm specifiers were requested; but --no-npm is specified")
|
return NpmPackageReqResolution::Err(anyhow!(
|
||||||
|
"npm specifiers were requested; but --no-npm is specified"
|
||||||
|
));
|
||||||
}
|
}
|
||||||
match self
|
|
||||||
|
let result = self
|
||||||
.npm_resolution
|
.npm_resolution
|
||||||
.resolve_package_req_as_pending(package_req)
|
.resolve_package_req_as_pending(package_req);
|
||||||
{
|
match result {
|
||||||
Ok(nv) => Ok(nv),
|
Ok(nv) => NpmPackageReqResolution::Ok(nv),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
bail!("{:#} Try retrieving the latest npm package information by running with --reload", err)
|
if self.npm_registry_api.mark_force_reload() {
|
||||||
|
log::debug!("Restarting npm specifier resolution to check for new registry information. Error: {:#}", err);
|
||||||
|
self.npm_registry_api.clear_memory_cache();
|
||||||
|
NpmPackageReqResolution::ReloadRegistryInfo(err.into())
|
||||||
|
} else {
|
||||||
|
NpmPackageReqResolution::Err(err.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1590,6 +1590,23 @@ fn reload_info_not_found_cache_but_exists_remote() {
|
||||||
.remove(version);
|
.remove(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_version_for_package(
|
||||||
|
deno_dir: &util::TempDir,
|
||||||
|
package: &str,
|
||||||
|
version: &str,
|
||||||
|
) {
|
||||||
|
let registry_json_path =
|
||||||
|
format!("npm/localhost_4545/npm/registry/{}/registry.json", package);
|
||||||
|
let mut registry_json: Value =
|
||||||
|
serde_json::from_str(&deno_dir.read_to_string(®istry_json_path))
|
||||||
|
.unwrap();
|
||||||
|
remove_version(&mut registry_json, version);
|
||||||
|
deno_dir.write(
|
||||||
|
®istry_json_path,
|
||||||
|
serde_json::to_string(®istry_json).unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// This tests that when a local machine doesn't have a version
|
// This tests that when a local machine doesn't have a version
|
||||||
// specified in a dependency that exists in the npm registry
|
// specified in a dependency that exists in the npm registry
|
||||||
let test_context = TestContextBuilder::for_npm()
|
let test_context = TestContextBuilder::for_npm()
|
||||||
|
@ -1604,68 +1621,144 @@ fn reload_info_not_found_cache_but_exists_remote() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// cache successfully to the deno_dir
|
// cache successfully to the deno_dir
|
||||||
let output = test_context.new_command().args("cache main.ts").run();
|
let output = test_context
|
||||||
|
.new_command()
|
||||||
|
.args("cache main.ts npm:@denotest/esm-basic@1.0.0")
|
||||||
|
.run();
|
||||||
output.assert_matches_text(concat!(
|
output.assert_matches_text(concat!(
|
||||||
|
"Download http://localhost:4545/npm/registry/@denotest/esm-basic\n",
|
||||||
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
|
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
|
||||||
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
|
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
|
||||||
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export/1.0.0.tgz\n",
|
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export/1.0.0.tgz\n",
|
||||||
|
"Download http://localhost:4545/npm/registry/@denotest/esm-basic/1.0.0.tgz\n",
|
||||||
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default/1.0.0.tgz\n",
|
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default/1.0.0.tgz\n",
|
||||||
));
|
));
|
||||||
|
|
||||||
// modify the package information in the cache to remove the latest version
|
// test in dependency
|
||||||
let registry_json_path = "npm/localhost_4545/npm/registry/@denotest/cjs-default-export/registry.json";
|
{
|
||||||
let mut registry_json: Value =
|
// modify the package information in the cache to remove the latest version
|
||||||
serde_json::from_str(&deno_dir.read_to_string(registry_json_path)).unwrap();
|
remove_version_for_package(
|
||||||
remove_version(&mut registry_json, "1.0.0");
|
deno_dir,
|
||||||
deno_dir.write(
|
"@denotest/cjs-default-export",
|
||||||
registry_json_path,
|
"1.0.0",
|
||||||
serde_json::to_string(®istry_json).unwrap(),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
// should error when `--cache-only` is used now because the version is not in the cache
|
// should error when `--cache-only` is used now because the version is not in the cache
|
||||||
let output = test_context
|
let output = test_context
|
||||||
.new_command()
|
.new_command()
|
||||||
.args("run --cached-only main.ts")
|
.args("run --cached-only main.ts")
|
||||||
.run();
|
.run();
|
||||||
output.assert_exit_code(1);
|
output.assert_exit_code(1);
|
||||||
output.assert_matches_text("error: Could not find npm package '@denotest/cjs-default-export' matching '^1.0.0'.\n");
|
output.assert_matches_text("error: Could not find npm package '@denotest/cjs-default-export' matching '^1.0.0'.\n");
|
||||||
|
|
||||||
// now try running without it, it should download the package now
|
// now try running without it, it should download the package now
|
||||||
let output = test_context.new_command().args("run main.ts").run();
|
let output = test_context.new_command().args("run main.ts").run();
|
||||||
output.assert_matches_text(concat!(
|
output.assert_matches_text(concat!(
|
||||||
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
|
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
|
||||||
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
|
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
|
||||||
"Node esm importing node cjs\n[WILDCARD]",
|
"Node esm importing node cjs\n[WILDCARD]",
|
||||||
));
|
));
|
||||||
output.assert_exit_code(0);
|
output.assert_exit_code(0);
|
||||||
|
}
|
||||||
|
|
||||||
// now remove the information for the top level package
|
// test in npm specifier
|
||||||
let registry_json_path = "npm/localhost_4545/npm/registry/@denotest/esm-import-cjs-default/registry.json";
|
{
|
||||||
let mut registry_json: Value =
|
// now remove the information for the top level package
|
||||||
serde_json::from_str(&deno_dir.read_to_string(registry_json_path)).unwrap();
|
remove_version_for_package(
|
||||||
remove_version(&mut registry_json, "1.0.0");
|
deno_dir,
|
||||||
deno_dir.write(
|
"@denotest/esm-import-cjs-default",
|
||||||
registry_json_path,
|
"1.0.0",
|
||||||
serde_json::to_string(®istry_json).unwrap(),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
// should error again for --cached-only
|
// should error for --cached-only
|
||||||
let output = test_context
|
let output = test_context
|
||||||
.new_command()
|
.new_command()
|
||||||
.args("run --cached-only main.ts")
|
.args("run --cached-only main.ts")
|
||||||
.run();
|
.run();
|
||||||
output.assert_exit_code(1);
|
output.assert_matches_text(concat!(
|
||||||
output.assert_matches_text(concat!(
|
"error: Could not find npm package '@denotest/esm-import-cjs-default' matching '1.0.0'.\n",
|
||||||
"error: Could not find npm package '@denotest/esm-import-cjs-default' matching '1.0.0'. Try retrieving the latest npm package information by running with --reload\n",
|
" at file:///[WILDCARD]/main.ts:1:8\n",
|
||||||
" at file:///[WILDCARD]/main.ts:1:8\n",
|
));
|
||||||
));
|
output.assert_exit_code(1);
|
||||||
|
|
||||||
// now try running without it, it currently will error, but this should work in the future
|
// now try running, it should work
|
||||||
// todo(https://github.com/denoland/deno/issues/16901): fix this
|
let output = test_context.new_command().args("run main.ts").run();
|
||||||
let output = test_context.new_command().args("run main.ts").run();
|
output.assert_matches_text(concat!(
|
||||||
output.assert_exit_code(1);
|
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
|
||||||
output.assert_matches_text(concat!(
|
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
|
||||||
"error: Could not find npm package '@denotest/esm-import-cjs-default' matching '1.0.0'. Try retrieving the latest npm package information by running with --reload\n",
|
"Node esm importing node cjs\n[WILDCARD]",
|
||||||
" at file:///[WILDCARD]/main.ts:1:8\n",
|
));
|
||||||
));
|
output.assert_exit_code(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test matched specifier in package.json
|
||||||
|
{
|
||||||
|
// write out a package.json and a new main.ts with a bare specifier
|
||||||
|
temp_dir.write("main.ts", "import '@denotest/esm-import-cjs-default';");
|
||||||
|
temp_dir.write(
|
||||||
|
"package.json",
|
||||||
|
r#"{ "dependencies": { "@denotest/esm-import-cjs-default": "1.0.0" }}"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove the top level package information again
|
||||||
|
remove_version_for_package(
|
||||||
|
deno_dir,
|
||||||
|
"@denotest/esm-import-cjs-default",
|
||||||
|
"1.0.0",
|
||||||
|
);
|
||||||
|
|
||||||
|
// should error for --cached-only
|
||||||
|
let output = test_context
|
||||||
|
.new_command()
|
||||||
|
.args("run --cached-only main.ts")
|
||||||
|
.run();
|
||||||
|
output.assert_matches_text(concat!(
|
||||||
|
"error: Could not find npm package '@denotest/esm-import-cjs-default' matching '1.0.0'.\n",
|
||||||
|
));
|
||||||
|
output.assert_exit_code(1);
|
||||||
|
|
||||||
|
// now try running, it should work
|
||||||
|
let output = test_context.new_command().args("run main.ts").run();
|
||||||
|
output.assert_matches_text(concat!(
|
||||||
|
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
|
||||||
|
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
|
||||||
|
"Initialize @denotest/cjs-default-export@1.0.0\n",
|
||||||
|
"Initialize @denotest/esm-import-cjs-default@1.0.0\n",
|
||||||
|
"Node esm importing node cjs\n[WILDCARD]",
|
||||||
|
));
|
||||||
|
output.assert_exit_code(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// temp other dependency in package.json
|
||||||
|
{
|
||||||
|
// write out a package.json that has another dependency
|
||||||
|
temp_dir.write(
|
||||||
|
"package.json",
|
||||||
|
r#"{ "dependencies": { "@denotest/esm-import-cjs-default": "1.0.0", "@denotest/esm-basic": "1.0.0" }}"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove the dependency's version
|
||||||
|
remove_version_for_package(deno_dir, "@denotest/esm-basic", "1.0.0");
|
||||||
|
|
||||||
|
// should error for --cached-only
|
||||||
|
let output = test_context
|
||||||
|
.new_command()
|
||||||
|
.args("run --cached-only main.ts")
|
||||||
|
.run();
|
||||||
|
output.assert_matches_text(concat!(
|
||||||
|
"error: Could not find npm package '@denotest/esm-basic' matching '1.0.0'.\n",
|
||||||
|
));
|
||||||
|
output.assert_exit_code(1);
|
||||||
|
|
||||||
|
// now try running, it should work and only initialize the new package
|
||||||
|
let output = test_context.new_command().args("run main.ts").run();
|
||||||
|
output.assert_matches_text(concat!(
|
||||||
|
"Download http://localhost:4545/npm/registry/@denotest/esm-basic\n",
|
||||||
|
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
|
||||||
|
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
|
||||||
|
"Initialize @denotest/esm-basic@1.0.0\n",
|
||||||
|
"Node esm importing node cjs\n[WILDCARD]",
|
||||||
|
));
|
||||||
|
output.assert_exit_code(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -486,7 +486,7 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
colors::red("error:")
|
colors::red("error:")
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
writeln!(writer, "{} {}", colors::red("error:"), err)
|
writeln!(writer, "{} {:#}", colors::red("error:"), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
|
|
4
cli/tools/vendor/test.rs
vendored
4
cli/tools/vendor/test.rs
vendored
|
@ -20,7 +20,7 @@ use deno_graph::ModuleGraph;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
|
|
||||||
use crate::cache::ParsedSourceCache;
|
use crate::cache::ParsedSourceCache;
|
||||||
use crate::npm::NpmRegistry;
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::NpmResolution;
|
use crate::npm::NpmResolution;
|
||||||
use crate::npm::PackageJsonDepsInstaller;
|
use crate::npm::PackageJsonDepsInstaller;
|
||||||
use crate::resolver::CliGraphResolver;
|
use crate::resolver::CliGraphResolver;
|
||||||
|
@ -264,7 +264,7 @@ async fn build_test_graph(
|
||||||
analyzer: &dyn deno_graph::ModuleAnalyzer,
|
analyzer: &dyn deno_graph::ModuleAnalyzer,
|
||||||
) -> ModuleGraph {
|
) -> ModuleGraph {
|
||||||
let resolver = original_import_map.map(|m| {
|
let resolver = original_import_map.map(|m| {
|
||||||
let npm_registry_api = NpmRegistry::new_uninitialized();
|
let npm_registry_api = CliNpmRegistryApi::new_uninitialized();
|
||||||
let npm_resolution =
|
let npm_resolution =
|
||||||
NpmResolution::new(npm_registry_api.clone(), None, None);
|
NpmResolution::new(npm_registry_api.clone(), None, None);
|
||||||
let deps_installer = PackageJsonDepsInstaller::new(
|
let deps_installer = PackageJsonDepsInstaller::new(
|
||||||
|
|
Loading…
Add table
Reference in a new issue