summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Hagemeister <marvin@deno.com>2024-10-24 20:03:56 +0200
committerGitHub <noreply@github.com>2024-10-24 20:03:56 +0200
commit5f0bb3c6f4328003012e98ba70ce18e4e2e842de (patch)
tree5d99b6f2868c70b105ca4ff83f2a7380f4da9ac5
parentc71e020668b40666aecfdffb1dbf979abcb41958 (diff)
fix: `.npmrc` settings not being passed to install/add command (#26473)
We weren't passing the resolved npmrc settings to the install commands. This lead us to always fall back to the default registry url instead of using the one from npmrc. Fixes https://github.com/denoland/deno/issues/26139 Fixes https://github.com/denoland/deno/issues/26033 Fixes https://github.com/denoland/deno/issues/25924 Fixes https://github.com/denoland/deno/issues/25822 Fixes https://github.com/denoland/deno/issues/26152 --------- Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com>
-rw-r--r--cli/args/mod.rs1
-rw-r--r--cli/cache/mod.rs1
-rw-r--r--cli/file_fetcher.rs30
-rw-r--r--cli/http_util.rs21
-rw-r--r--cli/lsp/npm.rs6
-rw-r--r--cli/lsp/registries.rs1
-rw-r--r--cli/npm/managed/cache/mod.rs2
-rw-r--r--cli/npm/managed/cache/registry_info.rs64
-rw-r--r--cli/npm/managed/mod.rs2
-rw-r--r--cli/npm/mod.rs25
-rw-r--r--cli/tools/registry/pm.rs6
-rw-r--r--tests/registry/npm-private3/@denotest3/basic/1.0.0/main.d.mts3
-rw-r--r--tests/registry/npm-private3/@denotest3/basic/1.0.0/main.mjs11
-rw-r--r--tests/registry/npm-private3/@denotest3/basic/1.0.0/other.mjs3
-rw-r--r--tests/registry/npm-private3/@denotest3/basic/1.0.0/package.json7
-rw-r--r--tests/specs/npm/npmrc_install_arg/.npmrc2
-rw-r--r--tests/specs/npm/npmrc_install_arg/__test__.jsonc23
-rw-r--r--tests/specs/npm/npmrc_install_arg/add.out4
-rw-r--r--tests/specs/npm/npmrc_install_arg/install.out4
-rw-r--r--tests/specs/npm/npmrc_install_arg/main.js5
-rw-r--r--tests/specs/npm/npmrc_install_arg/main.out2
-rw-r--r--tests/specs/npm/npmrc_install_arg/package.json5
-rw-r--r--tests/specs/npm/npmrc_no_auth/.npmrc1
-rw-r--r--tests/specs/npm/npmrc_no_auth/__test__.jsonc23
-rw-r--r--tests/specs/npm/npmrc_no_auth/add.out4
-rw-r--r--tests/specs/npm/npmrc_no_auth/install.out4
-rw-r--r--tests/specs/npm/npmrc_no_auth/main.js5
-rw-r--r--tests/specs/npm/npmrc_no_auth/main.out2
-rw-r--r--tests/specs/npm/npmrc_no_auth/package.json6
-rw-r--r--tests/specs/npm/npmrc_no_auth_install/.npmrc1
-rw-r--r--tests/specs/npm/npmrc_no_auth_install/__test__.jsonc14
-rw-r--r--tests/specs/npm/npmrc_no_auth_install/install.out3
-rw-r--r--tests/specs/npm/npmrc_no_auth_install/main.js5
-rw-r--r--tests/specs/npm/npmrc_no_auth_install/main.out2
-rw-r--r--tests/specs/npm/npmrc_no_auth_install/package.json7
-rw-r--r--tests/util/server/src/lib.rs3
-rw-r--r--tests/util/server/src/npm.rs32
-rw-r--r--tests/util/server/src/servers/mod.rs4
-rw-r--r--tests/util/server/src/servers/npm_registry.rs15
39 files changed, 317 insertions, 42 deletions
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index d8f553101..927f43e85 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -578,6 +578,7 @@ fn discover_npmrc(
let resolved = npmrc
.as_resolved(npm_registry_url())
.context("Failed to resolve .npmrc options")?;
+ log::debug!(".npmrc found at: '{}'", path.display());
Ok(Arc::new(resolved))
}
diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs
index ded163b4e..bf8f1b1f0 100644
--- a/cli/cache/mod.rs
+++ b/cli/cache/mod.rs
@@ -378,6 +378,7 @@ impl Loader for FetchCacher {
} else {
FetchPermissionsOptionRef::DynamicContainer(&permissions)
},
+ maybe_auth: None,
maybe_accept: None,
maybe_cache_setting: maybe_cache_setting.as_ref(),
},
diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs
index e92aca542..95d778f0b 100644
--- a/cli/file_fetcher.rs
+++ b/cli/file_fetcher.rs
@@ -24,6 +24,7 @@ use deno_graph::source::LoaderChecksum;
use deno_path_util::url_to_file_path;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::deno_web::BlobStore;
+use http::header;
use log::debug;
use std::borrow::Cow;
use std::collections::HashMap;
@@ -181,6 +182,7 @@ pub enum FetchPermissionsOptionRef<'a> {
pub struct FetchOptions<'a> {
pub specifier: &'a ModuleSpecifier,
pub permissions: FetchPermissionsOptionRef<'a>,
+ pub maybe_auth: Option<(header::HeaderName, header::HeaderValue)>,
pub maybe_accept: Option<&'a str>,
pub maybe_cache_setting: Option<&'a CacheSetting>,
}
@@ -350,6 +352,7 @@ impl FileFetcher {
maybe_accept: Option<&str>,
cache_setting: &CacheSetting,
maybe_checksum: Option<&LoaderChecksum>,
+ maybe_auth: Option<(header::HeaderName, header::HeaderValue)>,
) -> Result<FileOrRedirect, AnyError> {
debug!(
"FileFetcher::fetch_remote_no_follow - specifier: {}",
@@ -442,6 +445,7 @@ impl FileFetcher {
.as_ref()
.map(|(_, etag)| etag.clone()),
maybe_auth_token: maybe_auth_token.clone(),
+ maybe_auth: maybe_auth.clone(),
maybe_progress_guard: maybe_progress_guard.as_ref(),
})
.await?
@@ -538,7 +542,18 @@ impl FileFetcher {
specifier: &ModuleSpecifier,
) -> Result<File, AnyError> {
self
- .fetch_inner(specifier, FetchPermissionsOptionRef::AllowAll)
+ .fetch_inner(specifier, None, FetchPermissionsOptionRef::AllowAll)
+ .await
+ }
+
+ #[inline(always)]
+ pub async fn fetch_bypass_permissions_with_maybe_auth(
+ &self,
+ specifier: &ModuleSpecifier,
+ maybe_auth: Option<(header::HeaderName, header::HeaderValue)>,
+ ) -> Result<File, AnyError> {
+ self
+ .fetch_inner(specifier, maybe_auth, FetchPermissionsOptionRef::AllowAll)
.await
}
@@ -552,6 +567,7 @@ impl FileFetcher {
self
.fetch_inner(
specifier,
+ None,
FetchPermissionsOptionRef::StaticContainer(permissions),
)
.await
@@ -560,12 +576,14 @@ impl FileFetcher {
async fn fetch_inner(
&self,
specifier: &ModuleSpecifier,
+ maybe_auth: Option<(header::HeaderName, header::HeaderValue)>,
permissions: FetchPermissionsOptionRef<'_>,
) -> Result<File, AnyError> {
self
.fetch_with_options(FetchOptions {
specifier,
permissions,
+ maybe_auth,
maybe_accept: None,
maybe_cache_setting: None,
})
@@ -585,12 +603,14 @@ impl FileFetcher {
max_redirect: usize,
) -> Result<File, AnyError> {
let mut specifier = Cow::Borrowed(options.specifier);
+ let mut maybe_auth = options.maybe_auth.clone();
for _ in 0..=max_redirect {
match self
.fetch_no_follow_with_options(FetchNoFollowOptions {
fetch_options: FetchOptions {
specifier: &specifier,
permissions: options.permissions,
+ maybe_auth: maybe_auth.clone(),
maybe_accept: options.maybe_accept,
maybe_cache_setting: options.maybe_cache_setting,
},
@@ -602,6 +622,10 @@ impl FileFetcher {
return Ok(file);
}
FileOrRedirect::Redirect(redirect_specifier) => {
+ // If we were redirected to another origin, don't send the auth header anymore.
+ if redirect_specifier.origin() != specifier.origin() {
+ maybe_auth = None;
+ }
specifier = Cow::Owned(redirect_specifier);
}
}
@@ -666,6 +690,7 @@ impl FileFetcher {
options.maybe_accept,
options.maybe_cache_setting.unwrap_or(&self.cache_setting),
maybe_checksum,
+ options.maybe_auth,
)
.await
}
@@ -756,6 +781,7 @@ mod tests {
FetchOptions {
specifier,
permissions: FetchPermissionsOptionRef::AllowAll,
+ maybe_auth: None,
maybe_accept: None,
maybe_cache_setting: Some(&file_fetcher.cache_setting),
},
@@ -1255,6 +1281,7 @@ mod tests {
FetchOptions {
specifier: &specifier,
permissions: FetchPermissionsOptionRef::AllowAll,
+ maybe_auth: None,
maybe_accept: None,
maybe_cache_setting: Some(&file_fetcher.cache_setting),
},
@@ -1268,6 +1295,7 @@ mod tests {
FetchOptions {
specifier: &specifier,
permissions: FetchPermissionsOptionRef::AllowAll,
+ maybe_auth: None,
maybe_accept: None,
maybe_cache_setting: Some(&file_fetcher.cache_setting),
},
diff --git a/cli/http_util.rs b/cli/http_util.rs
index 9c9ae9e41..4b17936d6 100644
--- a/cli/http_util.rs
+++ b/cli/http_util.rs
@@ -19,6 +19,7 @@ use deno_runtime::deno_fetch;
use deno_runtime::deno_fetch::create_http_client;
use deno_runtime::deno_fetch::CreateHttpClientOptions;
use deno_runtime::deno_tls::RootCertStoreProvider;
+use http::header;
use http::header::HeaderName;
use http::header::HeaderValue;
use http::header::ACCEPT;
@@ -204,6 +205,7 @@ pub struct FetchOnceArgs<'a> {
pub maybe_accept: Option<String>,
pub maybe_etag: Option<String>,
pub maybe_auth_token: Option<AuthToken>,
+ pub maybe_auth: Option<(header::HeaderName, header::HeaderValue)>,
pub maybe_progress_guard: Option<&'a UpdateGuard>,
}
@@ -382,6 +384,8 @@ impl HttpClient {
request
.headers_mut()
.insert(AUTHORIZATION, authorization_val);
+ } else if let Some((header, value)) = args.maybe_auth {
+ request.headers_mut().insert(header, value);
}
if let Some(accept) = args.maybe_accept {
let accepts_val = HeaderValue::from_str(&accept)?;
@@ -792,6 +796,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, headers)) = result {
@@ -818,6 +823,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, headers)) = result {
@@ -845,6 +851,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, headers)) = result {
@@ -866,6 +873,7 @@ mod test {
maybe_etag: Some("33a64df551425fcc55e".to_string()),
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
assert_eq!(res.unwrap(), FetchOnceResult::NotModified);
@@ -885,6 +893,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, headers)) = result {
@@ -914,6 +923,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, _)) = result {
@@ -939,6 +949,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Redirect(url, _)) = result {
@@ -974,6 +985,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, headers)) = result {
@@ -1021,6 +1033,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
@@ -1083,6 +1096,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
@@ -1136,6 +1150,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, headers)) = result {
@@ -1177,6 +1192,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, headers)) = result {
@@ -1199,6 +1215,7 @@ mod test {
maybe_etag: Some("33a64df551425fcc55e".to_string()),
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
assert_eq!(res.unwrap(), FetchOnceResult::NotModified);
@@ -1233,6 +1250,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
if let Ok(FetchOnceResult::Code(body, headers)) = result {
@@ -1262,6 +1280,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
assert!(result.is_err());
@@ -1283,6 +1302,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
@@ -1306,6 +1326,7 @@ mod test {
maybe_etag: None,
maybe_auth_token: None,
maybe_progress_guard: None,
+ maybe_auth: None,
})
.await;
diff --git a/cli/lsp/npm.rs b/cli/lsp/npm.rs
index 8bdeb7e7d..2decfc342 100644
--- a/cli/lsp/npm.rs
+++ b/cli/lsp/npm.rs
@@ -4,6 +4,7 @@ use dashmap::DashMap;
use deno_core::anyhow::anyhow;
use deno_core::error::AnyError;
use deno_core::serde_json;
+use deno_npm::npm_rc::NpmRc;
use deno_semver::package::PackageNv;
use deno_semver::Version;
use serde::Deserialize;
@@ -25,7 +26,10 @@ pub struct CliNpmSearchApi {
impl CliNpmSearchApi {
pub fn new(file_fetcher: Arc<FileFetcher>) -> Self {
- let resolver = NpmFetchResolver::new(file_fetcher.clone());
+ let resolver = NpmFetchResolver::new(
+ file_fetcher.clone(),
+ Arc::new(NpmRc::default().as_resolved(npm_registry_url()).unwrap()),
+ );
Self {
file_fetcher,
resolver,
diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs
index 5f7ce0082..ade353e68 100644
--- a/cli/lsp/registries.rs
+++ b/cli/lsp/registries.rs
@@ -482,6 +482,7 @@ impl ModuleRegistry {
.fetch_with_options(FetchOptions {
specifier: &specifier,
permissions: FetchPermissionsOptionRef::AllowAll,
+ maybe_auth: None,
maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"),
maybe_cache_setting: None,
})
diff --git a/cli/npm/managed/cache/mod.rs b/cli/npm/managed/cache/mod.rs
index fa0e8c8a5..aaec48668 100644
--- a/cli/npm/managed/cache/mod.rs
+++ b/cli/npm/managed/cache/mod.rs
@@ -26,7 +26,7 @@ use crate::cache::CACHE_PERM;
use crate::util::fs::atomic_write_file_with_retries;
use crate::util::fs::hard_link_dir_recursive;
-mod registry_info;
+pub mod registry_info;
mod tarball;
mod tarball_extract;
diff --git a/cli/npm/managed/cache/registry_info.rs b/cli/npm/managed/cache/registry_info.rs
index 6c4a7503b..6d39d3c13 100644
--- a/cli/npm/managed/cache/registry_info.rs
+++ b/cli/npm/managed/cache/registry_info.rs
@@ -84,7 +84,7 @@ impl RegistryInfoDownloader {
self.load_package_info_inner(name).await.with_context(|| {
format!(
"Error getting response at {} for package \"{}\"",
- self.get_package_url(name),
+ get_package_url(&self.npmrc, name),
name
)
})
@@ -190,7 +190,7 @@ impl RegistryInfoDownloader {
fn create_load_future(self: &Arc<Self>, name: &str) -> LoadFuture {
let downloader = self.clone();
- let package_url = self.get_package_url(name);
+ let package_url = get_package_url(&self.npmrc, name);
let registry_config = self.npmrc.get_registry_config(name);
let maybe_auth_header =
match maybe_auth_header_for_npm_registry(registry_config) {
@@ -239,36 +239,36 @@ impl RegistryInfoDownloader {
.map(|r| r.map_err(Arc::new))
.boxed_local()
}
+}
- fn get_package_url(&self, name: &str) -> Url {
- let registry_url = self.npmrc.get_registry_url(name);
- // The '/' character in scoped package names "@scope/name" must be
- // encoded for older third party registries. Newer registries and
- // npm itself support both ways
- // - encoded: https://registry.npmjs.org/@rollup%2fplugin-json
- // - non-ecoded: https://registry.npmjs.org/@rollup/plugin-json
- // To support as many third party registries as possible we'll
- // always encode the '/' character.
+pub fn get_package_url(npmrc: &ResolvedNpmRc, name: &str) -> Url {
+ let registry_url = npmrc.get_registry_url(name);
+ // The '/' character in scoped package names "@scope/name" must be
+ // encoded for older third party registries. Newer registries and
+ // npm itself support both ways
+ // - encoded: https://registry.npmjs.org/@rollup%2fplugin-json
+ // - non-ecoded: https://registry.npmjs.org/@rollup/plugin-json
+ // To support as many third party registries as possible we'll
+ // always encode the '/' character.
- // list of all characters used in npm packages:
- // !, ', (, ), *, -, ., /, [0-9], @, [A-Za-z], _, ~
- const ASCII_SET: percent_encoding::AsciiSet =
- percent_encoding::NON_ALPHANUMERIC
- .remove(b'!')
- .remove(b'\'')
- .remove(b'(')
- .remove(b')')
- .remove(b'*')
- .remove(b'-')
- .remove(b'.')
- .remove(b'@')
- .remove(b'_')
- .remove(b'~');
- let name = percent_encoding::utf8_percent_encode(name, &ASCII_SET);
- registry_url
- // Ensure that scoped package name percent encoding is lower cased
- // to match npm.
- .join(&name.to_string().replace("%2F", "%2f"))
- .unwrap()
- }
+ // list of all characters used in npm packages:
+ // !, ', (, ), *, -, ., /, [0-9], @, [A-Za-z], _, ~
+ const ASCII_SET: percent_encoding::AsciiSet =
+ percent_encoding::NON_ALPHANUMERIC
+ .remove(b'!')
+ .remove(b'\'')
+ .remove(b'(')
+ .remove(b')')
+ .remove(b'*')
+ .remove(b'-')
+ .remove(b'.')
+ .remove(b'@')
+ .remove(b'_')
+ .remove(b'~');
+ let name = percent_encoding::utf8_percent_encode(name, &ASCII_SET);
+ registry_url
+ // Ensure that scoped package name percent encoding is lower cased
+ // to match npm.
+ .join(&name.to_string().replace("%2F", "%2f"))
+ .unwrap()
}
diff --git a/cli/npm/managed/mod.rs b/cli/npm/managed/mod.rs
index ec50a9c65..d0880557f 100644
--- a/cli/npm/managed/mod.rs
+++ b/cli/npm/managed/mod.rs
@@ -55,7 +55,7 @@ use super::CliNpmResolver;
use super::InnerCliNpmResolverRef;
use super::ResolvePkgFolderFromDenoReqError;
-mod cache;
+pub mod cache;
mod registry;
mod resolution;
mod resolvers;
diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs
index 53baaf77b..f48f7a740 100644
--- a/cli/npm/mod.rs
+++ b/cli/npm/mod.rs
@@ -8,10 +8,12 @@ use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
+use common::maybe_auth_header_for_npm_registry;
use dashmap::DashMap;
use deno_ast::ModuleSpecifier;
use deno_core::error::AnyError;
use deno_core::serde_json;
+use deno_npm::npm_rc::ResolvedNpmRc;
use deno_npm::registry::NpmPackageInfo;
use deno_resolver::npm::ByonmNpmResolver;
use deno_resolver::npm::ByonmResolvePkgFolderFromDenoReqError;
@@ -19,10 +21,10 @@ use deno_runtime::deno_node::NodeRequireResolver;
use deno_runtime::ops::process::NpmProcessStateProvider;
use deno_semver::package::PackageNv;
use deno_semver::package::PackageReq;
+use managed::cache::registry_info::get_package_url;
use node_resolver::NpmResolver;
use thiserror::Error;
-use crate::args::npm_registry_url;
use crate::file_fetcher::FileFetcher;
pub use self::byonm::CliByonmNpmResolver;
@@ -115,14 +117,19 @@ pub struct NpmFetchResolver {
nv_by_req: DashMap<PackageReq, Option<PackageNv>>,
info_by_name: DashMap<String, Option<Arc<NpmPackageInfo>>>,
file_fetcher: Arc<FileFetcher>,
+ npmrc: Arc<ResolvedNpmRc>,
}
impl NpmFetchResolver {
- pub fn new(file_fetcher: Arc<FileFetcher>) -> Self {
+ pub fn new(
+ file_fetcher: Arc<FileFetcher>,
+ npmrc: Arc<ResolvedNpmRc>,
+ ) -> Self {
Self {
nv_by_req: Default::default(),
info_by_name: Default::default(),
file_fetcher,
+ npmrc,
}
}
@@ -157,11 +164,21 @@ impl NpmFetchResolver {
return info.value().clone();
}
let fetch_package_info = || async {
- let info_url = npm_registry_url().join(name).ok()?;
+ let info_url = get_package_url(&self.npmrc, name);
let file_fetcher = self.file_fetcher.clone();
+ let registry_config = self.npmrc.get_registry_config(name);
+ // TODO(bartlomieju): this should error out, not use `.ok()`.
+ let maybe_auth_header =
+ maybe_auth_header_for_npm_registry(registry_config).ok()?;
// spawn due to the lsp's `Send` requirement
let file = deno_core::unsync::spawn(async move {
- file_fetcher.fetch_bypass_permissions(&info_url).await.ok()
+ file_fetcher
+ .fetch_bypass_permissions_with_maybe_auth(
+ &info_url,
+ maybe_auth_header,
+ )
+ .await
+ .ok()
})
.await
.ok()??;
diff --git a/cli/tools/registry/pm.rs b/cli/tools/registry/pm.rs
index 2060b9a13..d1be901d6 100644
--- a/cli/tools/registry/pm.rs
+++ b/cli/tools/registry/pm.rs
@@ -367,10 +367,14 @@ pub async fn add(
Default::default(),
None,
);
+
+ let npmrc = cli_factory.cli_options().unwrap().npmrc();
+
deps_file_fetcher.set_download_log_level(log::Level::Trace);
let deps_file_fetcher = Arc::new(deps_file_fetcher);
let jsr_resolver = Arc::new(JsrFetchResolver::new(deps_file_fetcher.clone()));
- let npm_resolver = Arc::new(NpmFetchResolver::new(deps_file_fetcher));
+ let npm_resolver =
+ Arc::new(NpmFetchResolver::new(deps_file_fetcher, npmrc.clone()));
let mut selected_packages = Vec::with_capacity(add_flags.packages.len());
let mut package_reqs = Vec::with_capacity(add_flags.packages.len());
diff --git a/tests/registry/npm-private3/@denotest3/basic/1.0.0/main.d.mts b/tests/registry/npm-private3/@denotest3/basic/1.0.0/main.d.mts
new file mode 100644
index 000000000..29da1e6d7
--- /dev/null
+++ b/tests/registry/npm-private3/@denotest3/basic/1.0.0/main.d.mts
@@ -0,0 +1,3 @@
+export declare function setValue(val: number): void;
+export declare function getValue(): number;
+export declare const url: string;
diff --git a/tests/registry/npm-private3/@denotest3/basic/1.0.0/main.mjs b/tests/registry/npm-private3/@denotest3/basic/1.0.0/main.mjs
new file mode 100644
index 000000000..0a44f7585
--- /dev/null
+++ b/tests/registry/npm-private3/@denotest3/basic/1.0.0/main.mjs
@@ -0,0 +1,11 @@
+let value = 0;
+
+export function setValue(newValue) {
+ value = newValue;
+}
+
+export function getValue() {
+ return value;
+}
+
+export const url = import.meta.url;
diff --git a/tests/registry/npm-private3/@denotest3/basic/1.0.0/other.mjs b/tests/registry/npm-private3/@denotest3/basic/1.0.0/other.mjs
new file mode 100644
index 000000000..00ed99da4
--- /dev/null
+++ b/tests/registry/npm-private3/@denotest3/basic/1.0.0/other.mjs
@@ -0,0 +1,3 @@
+export function hello() {
+ return "hello, world!";
+} \ No newline at end of file
diff --git a/tests/registry/npm-private3/@denotest3/basic/1.0.0/package.json b/tests/registry/npm-private3/@denotest3/basic/1.0.0/package.json
new file mode 100644
index 000000000..ce6ea3383
--- /dev/null
+++ b/tests/registry/npm-private3/@denotest3/basic/1.0.0/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "@denotest3/basic",
+ "version": "1.0.0",
+ "type": "module",
+ "main": "main.mjs",
+ "types": "main.d.mts"
+}
diff --git a/tests/specs/npm/npmrc_install_arg/.npmrc b/tests/specs/npm/npmrc_install_arg/.npmrc
new file mode 100644
index 000000000..de3704b92
--- /dev/null
+++ b/tests/specs/npm/npmrc_install_arg/.npmrc
@@ -0,0 +1,2 @@
+@denotest:registry=http://localhost:4261/
+//localhost:4261/:_authToken=private-reg-token
diff --git a/tests/specs/npm/npmrc_install_arg/__test__.jsonc b/tests/specs/npm/npmrc_install_arg/__test__.jsonc
new file mode 100644
index 000000000..f34cfe116
--- /dev/null
+++ b/tests/specs/npm/npmrc_install_arg/__test__.jsonc
@@ -0,0 +1,23 @@
+{
+ "tempDir": true,
+ "tests": {
+ "deno_install_add": {
+ "steps": [{
+ "args": "install npm:@denotest/basic",
+ "output": "install.out"
+ }, {
+ "args": "run -A main.js",
+ "output": "main.out"
+ }]
+ },
+ "deno_add": {
+ "steps": [{
+ "args": "add npm:@denotest/basic",
+ "output": "add.out"
+ }, {
+ "args": "run -A main.js",
+ "output": "main.out"
+ }]
+ }
+ }
+}
diff --git a/tests/specs/npm/npmrc_install_arg/add.out b/tests/specs/npm/npmrc_install_arg/add.out
new file mode 100644
index 000000000..11948e54d
--- /dev/null
+++ b/tests/specs/npm/npmrc_install_arg/add.out
@@ -0,0 +1,4 @@
+Add npm:@denotest/basic@1.0.0
+Download http://localhost:4261/@denotest%2fbasic
+Download http://localhost:4261/@denotest/basic/1.0.0.tgz
+Initialize @denotest/basic@1.0.0
diff --git a/tests/specs/npm/npmrc_install_arg/install.out b/tests/specs/npm/npmrc_install_arg/install.out
new file mode 100644
index 000000000..11948e54d
--- /dev/null
+++ b/tests/specs/npm/npmrc_install_arg/install.out
@@ -0,0 +1,4 @@
+Add npm:@denotest/basic@1.0.0
+Download http://localhost:4261/@denotest%2fbasic
+Download http://localhost:4261/@denotest/basic/1.0.0.tgz
+Initialize @denotest/basic@1.0.0
diff --git a/tests/specs/npm/npmrc_install_arg/main.js b/tests/specs/npm/npmrc_install_arg/main.js
new file mode 100644
index 000000000..e8ccf7611
--- /dev/null
+++ b/tests/specs/npm/npmrc_install_arg/main.js
@@ -0,0 +1,5 @@
+import { getValue, setValue } from "@denotest/basic";
+
+console.log(getValue());
+setValue(42);
+console.log(getValue());
diff --git a/tests/specs/npm/npmrc_install_arg/main.out b/tests/specs/npm/npmrc_install_arg/main.out
new file mode 100644
index 000000000..dcd912c89
--- /dev/null
+++ b/tests/specs/npm/npmrc_install_arg/main.out
@@ -0,0 +1,2 @@
+0
+42
diff --git a/tests/specs/npm/npmrc_install_arg/package.json b/tests/specs/npm/npmrc_install_arg/package.json
new file mode 100644
index 000000000..c1318b361
--- /dev/null
+++ b/tests/specs/npm/npmrc_install_arg/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "npmrc_test",
+ "version": "0.0.1",
+ "dependencies": {}
+}
diff --git a/tests/specs/npm/npmrc_no_auth/.npmrc b/tests/specs/npm/npmrc_no_auth/.npmrc
new file mode 100644
index 000000000..860a7c3d9
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth/.npmrc
@@ -0,0 +1 @@
+@denotest3:registry=http://localhost:4263/
diff --git a/tests/specs/npm/npmrc_no_auth/__test__.jsonc b/tests/specs/npm/npmrc_no_auth/__test__.jsonc
new file mode 100644
index 000000000..efd04f0e4
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth/__test__.jsonc
@@ -0,0 +1,23 @@
+{
+ "tempDir": true,
+ "tests": {
+ "deno_install_arg": {
+ "steps": [{
+ "args": "install npm:@denotest3/basic",
+ "output": "install.out"
+ }, {
+ "args": "run -A main.js",
+ "output": "main.out"
+ }]
+ },
+ "deno_add_arg": {
+ "steps": [{
+ "args": "add npm:@denotest3/basic",
+ "output": "add.out"
+ }, {
+ "args": "run -A main.js",
+ "output": "main.out"
+ }]
+ }
+ }
+}
diff --git a/tests/specs/npm/npmrc_no_auth/add.out b/tests/specs/npm/npmrc_no_auth/add.out
new file mode 100644
index 000000000..31b34da13
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth/add.out
@@ -0,0 +1,4 @@
+Add npm:@denotest3/basic@1.0.0
+Download http://localhost:4263/@denotest3%2fbasic
+Download http://localhost:4263/@denotest3/basic/1.0.0.tgz
+Initialize @denotest3/basic@1.0.0
diff --git a/tests/specs/npm/npmrc_no_auth/install.out b/tests/specs/npm/npmrc_no_auth/install.out
new file mode 100644
index 000000000..31b34da13
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth/install.out
@@ -0,0 +1,4 @@
+Add npm:@denotest3/basic@1.0.0
+Download http://localhost:4263/@denotest3%2fbasic
+Download http://localhost:4263/@denotest3/basic/1.0.0.tgz
+Initialize @denotest3/basic@1.0.0
diff --git a/tests/specs/npm/npmrc_no_auth/main.js b/tests/specs/npm/npmrc_no_auth/main.js
new file mode 100644
index 000000000..22713bb0d
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth/main.js
@@ -0,0 +1,5 @@
+import { getValue, setValue } from "@denotest3/basic";
+
+console.log(getValue());
+setValue(42);
+console.log(getValue());
diff --git a/tests/specs/npm/npmrc_no_auth/main.out b/tests/specs/npm/npmrc_no_auth/main.out
new file mode 100644
index 000000000..dcd912c89
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth/main.out
@@ -0,0 +1,2 @@
+0
+42
diff --git a/tests/specs/npm/npmrc_no_auth/package.json b/tests/specs/npm/npmrc_no_auth/package.json
new file mode 100644
index 000000000..dddaaac46
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "npmrc_test",
+ "version": "0.0.1",
+ "dependencies": {
+ }
+}
diff --git a/tests/specs/npm/npmrc_no_auth_install/.npmrc b/tests/specs/npm/npmrc_no_auth_install/.npmrc
new file mode 100644
index 000000000..860a7c3d9
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth_install/.npmrc
@@ -0,0 +1 @@
+@denotest3:registry=http://localhost:4263/
diff --git a/tests/specs/npm/npmrc_no_auth_install/__test__.jsonc b/tests/specs/npm/npmrc_no_auth_install/__test__.jsonc
new file mode 100644
index 000000000..56a598e3b
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth_install/__test__.jsonc
@@ -0,0 +1,14 @@
+{
+ "tempDir": true,
+ "tests": {
+ "deno_install_arg": {
+ "steps": [{
+ "args": "install",
+ "output": "install.out"
+ }, {
+ "args": "run -A main.js",
+ "output": "main.out"
+ }]
+ }
+ }
+}
diff --git a/tests/specs/npm/npmrc_no_auth_install/install.out b/tests/specs/npm/npmrc_no_auth_install/install.out
new file mode 100644
index 000000000..b82747af7
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth_install/install.out
@@ -0,0 +1,3 @@
+Download http://localhost:4263/@denotest3%2fbasic
+Download http://localhost:4263/@denotest3/basic/1.0.0.tgz
+Initialize @denotest3/basic@1.0.0
diff --git a/tests/specs/npm/npmrc_no_auth_install/main.js b/tests/specs/npm/npmrc_no_auth_install/main.js
new file mode 100644
index 000000000..22713bb0d
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth_install/main.js
@@ -0,0 +1,5 @@
+import { getValue, setValue } from "@denotest3/basic";
+
+console.log(getValue());
+setValue(42);
+console.log(getValue());
diff --git a/tests/specs/npm/npmrc_no_auth_install/main.out b/tests/specs/npm/npmrc_no_auth_install/main.out
new file mode 100644
index 000000000..dcd912c89
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth_install/main.out
@@ -0,0 +1,2 @@
+0
+42
diff --git a/tests/specs/npm/npmrc_no_auth_install/package.json b/tests/specs/npm/npmrc_no_auth_install/package.json
new file mode 100644
index 000000000..2d4fb15ba
--- /dev/null
+++ b/tests/specs/npm/npmrc_no_auth_install/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "npmrc_test",
+ "version": "0.0.1",
+ "dependencies": {
+ "@denotest3/basic": "1.0.0"
+ }
+}
diff --git a/tests/util/server/src/lib.rs b/tests/util/server/src/lib.rs
index 88e8287e0..e4a2cc02e 100644
--- a/tests/util/server/src/lib.rs
+++ b/tests/util/server/src/lib.rs
@@ -307,7 +307,7 @@ async fn get_tcp_listener_stream(
futures::stream::select_all(listeners)
}
-pub const TEST_SERVERS_COUNT: usize = 30;
+pub const TEST_SERVERS_COUNT: usize = 32;
#[derive(Default)]
struct HttpServerCount {
@@ -360,6 +360,7 @@ impl Default for HttpServerStarter {
let mut ready_count = 0;
for maybe_line in lines {
if let Ok(line) = maybe_line {
+ eprintln!("LINE: {}", line);
if line.starts_with("ready:") {
ready_count += 1;
}
diff --git a/tests/util/server/src/npm.rs b/tests/util/server/src/npm.rs
index f1c341738..4b17b95f7 100644
--- a/tests/util/server/src/npm.rs
+++ b/tests/util/server/src/npm.rs
@@ -18,6 +18,7 @@ use crate::PathRef;
pub const DENOTEST_SCOPE_NAME: &str = "@denotest";
pub const DENOTEST2_SCOPE_NAME: &str = "@denotest2";
+pub const DENOTEST3_SCOPE_NAME: &str = "@denotest3";
pub static PUBLIC_TEST_NPM_REGISTRY: Lazy<TestNpmRegistry> = Lazy::new(|| {
TestNpmRegistry::new(
@@ -54,6 +55,18 @@ pub static PRIVATE_TEST_NPM_REGISTRY_2: Lazy<TestNpmRegistry> =
)
});
+pub static PRIVATE_TEST_NPM_REGISTRY_3: Lazy<TestNpmRegistry> =
+ Lazy::new(|| {
+ TestNpmRegistry::new(
+ NpmRegistryKind::Private,
+ &format!(
+ "http://localhost:{}",
+ crate::servers::PRIVATE_NPM_REGISTRY_3_PORT
+ ),
+ "npm-private3",
+ )
+ });
+
pub enum NpmRegistryKind {
Public,
Private,
@@ -90,6 +103,7 @@ impl TestNpmRegistry {
}
pub fn root_dir(&self) -> PathRef {
+ eprintln!("root {}", self.local_path);
tests_path().join("registry").join(&self.local_path)
}
@@ -106,6 +120,7 @@ impl TestNpmRegistry {
}
pub fn registry_file(&self, name: &str) -> Result<Option<Vec<u8>>> {
+ eprintln!("registry file {}", name);
self.get_package_property(name, |p| p.registry_file.as_bytes().to_vec())
}
@@ -123,6 +138,7 @@ impl TestNpmRegistry {
package_name: &str,
func: impl FnOnce(&CustomNpmPackage) -> TResult,
) -> Result<Option<TResult>> {
+ eprintln!("get package property {}", package_name);
// it's ok if multiple threads race here as they will do the same work twice
if !self.cache.lock().contains_key(package_name) {
match get_npm_package(&self.hostname, &self.local_path, package_name)? {
@@ -139,6 +155,7 @@ impl TestNpmRegistry {
&self,
uri_path: &'s str,
) -> Option<(&'s str, &'s str)> {
+ eprintln!("GEETT {}", uri_path);
let prefix1 = format!("/{}/", DENOTEST_SCOPE_NAME);
let prefix2 = format!("/{}%2f", DENOTEST_SCOPE_NAME);
@@ -161,6 +178,17 @@ impl TestNpmRegistry {
return Some((DENOTEST2_SCOPE_NAME, package_name_with_path));
}
+ let prefix1 = format!("/{}/", DENOTEST3_SCOPE_NAME);
+ let prefix2 = format!("/{}%2f", DENOTEST3_SCOPE_NAME);
+
+ let maybe_package_name_with_path = uri_path
+ .strip_prefix(&prefix1)
+ .or_else(|| uri_path.strip_prefix(&prefix2));
+
+ if let Some(package_name_with_path) = maybe_package_name_with_path {
+ return Some((DENOTEST3_SCOPE_NAME, package_name_with_path));
+ }
+
None
}
}
@@ -170,6 +198,10 @@ fn get_npm_package(
local_path: &str,
package_name: &str,
) -> Result<Option<CustomNpmPackage>> {
+ eprintln!(
+ "get npm package {} {} {}",
+ registry_hostname, local_path, package_name
+ );
let registry_hostname = if package_name == "@denotest/tarballs-privateserver2"
{
"http://localhost:4262"
diff --git a/tests/util/server/src/servers/mod.rs b/tests/util/server/src/servers/mod.rs
index 3e18aafce..3a9c44010 100644
--- a/tests/util/server/src/servers/mod.rs
+++ b/tests/util/server/src/servers/mod.rs
@@ -91,6 +91,7 @@ const PROVENANCE_MOCK_SERVER_PORT: u16 = 4251;
pub(crate) const PUBLIC_NPM_REGISTRY_PORT: u16 = 4260;
pub(crate) const PRIVATE_NPM_REGISTRY_1_PORT: u16 = 4261;
pub(crate) const PRIVATE_NPM_REGISTRY_2_PORT: u16 = 4262;
+pub(crate) const PRIVATE_NPM_REGISTRY_3_PORT: u16 = 4263;
// Use the single-threaded scheduler. The hyper server is used as a point of
// comparison for the (single-threaded!) benchmarks in cli/bench. We're not
@@ -143,6 +144,8 @@ pub async fn run_all_servers() {
npm_registry::private_npm_registry1(PRIVATE_NPM_REGISTRY_1_PORT);
let private_npm_registry_2_server_futs =
npm_registry::private_npm_registry2(PRIVATE_NPM_REGISTRY_2_PORT);
+ let private_npm_registry_3_server_futs =
+ npm_registry::private_npm_registry3(PRIVATE_NPM_REGISTRY_3_PORT);
let mut futures = vec![
redirect_server_fut.boxed_local(),
@@ -173,6 +176,7 @@ pub async fn run_all_servers() {
futures.extend(npm_registry_server_futs);
futures.extend(private_npm_registry_1_server_futs);
futures.extend(private_npm_registry_2_server_futs);
+ futures.extend(private_npm_registry_3_server_futs);
assert_eq!(futures.len(), TEST_SERVERS_COUNT);
diff --git a/tests/util/server/src/servers/npm_registry.rs b/tests/util/server/src/servers/npm_registry.rs
index acbd9cab4..4ada468fa 100644
--- a/tests/util/server/src/servers/npm_registry.rs
+++ b/tests/util/server/src/servers/npm_registry.rs
@@ -56,6 +56,14 @@ pub fn private_npm_registry2(port: u16) -> Vec<LocalBoxFuture<'static, ()>> {
)
}
+pub fn private_npm_registry3(port: u16) -> Vec<LocalBoxFuture<'static, ()>> {
+ run_npm_server(
+ port,
+ "npm private registry server error",
+ private_npm_registry3_handler,
+ )
+}
+
fn run_npm_server<F, S>(
port: u16,
error_msg: &'static str,
@@ -141,6 +149,13 @@ async fn private_npm_registry2_handler(
handle_req_for_registry(req, &npm::PRIVATE_TEST_NPM_REGISTRY_2).await
}
+async fn private_npm_registry3_handler(
+ req: Request<hyper::body::Incoming>,
+) -> Result<Response<UnsyncBoxBody<Bytes, Infallible>>, anyhow::Error> {
+ // No auth for this registry
+ handle_req_for_registry(req, &npm::PRIVATE_TEST_NPM_REGISTRY_3).await
+}
+
async fn handle_req_for_registry(
req: Request<Incoming>,
test_npm_registry: &npm::TestNpmRegistry,