mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
FUTURE: initial support for .npmrc file (#23560)
This commit adds initial support for ".npmrc" files. Currently we only discover ".npmrc" files next to "package.json" files and discovering these files in user home dir is left for a follow up. This pass supports "_authToken" and "_auth" configuration for providing authentication. LSP support has been left for a follow up PR. Towards https://github.com/denoland/deno/issues/16105
This commit is contained in:
parent
5de30c5323
commit
959739f609
65 changed files with 611 additions and 164 deletions
|
@ -13,6 +13,8 @@ use ::import_map::ImportMap;
|
||||||
use deno_ast::SourceMapOption;
|
use deno_ast::SourceMapOption;
|
||||||
use deno_core::resolve_url_or_path;
|
use deno_core::resolve_url_or_path;
|
||||||
use deno_graph::GraphKind;
|
use deno_graph::GraphKind;
|
||||||
|
use deno_npm::npm_rc::NpmRc;
|
||||||
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
|
@ -546,6 +548,83 @@ fn discover_package_json(
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Discover `.npmrc` file - currently we only support it next to `package.json`
|
||||||
|
/// or next to `deno.json`.
|
||||||
|
///
|
||||||
|
/// In the future we will need to support it in user directory or global directory
|
||||||
|
/// as per https://docs.npmjs.com/cli/v10/configuring-npm/npmrc#files.
|
||||||
|
fn discover_npmrc(
|
||||||
|
maybe_package_json_path: Option<PathBuf>,
|
||||||
|
maybe_deno_json_path: Option<PathBuf>,
|
||||||
|
) -> Result<Arc<ResolvedNpmRc>, AnyError> {
|
||||||
|
if !*DENO_FUTURE {
|
||||||
|
return Ok(create_default_npmrc());
|
||||||
|
}
|
||||||
|
|
||||||
|
const NPMRC_NAME: &str = ".npmrc";
|
||||||
|
|
||||||
|
fn get_env_var(var_name: &str) -> Option<String> {
|
||||||
|
std::env::var(var_name).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_to_read_npmrc(
|
||||||
|
dir: &Path,
|
||||||
|
) -> Result<Option<(String, PathBuf)>, AnyError> {
|
||||||
|
let path = dir.join(NPMRC_NAME);
|
||||||
|
let maybe_source = match std::fs::read_to_string(&path) {
|
||||||
|
Ok(source) => Some(source),
|
||||||
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => None,
|
||||||
|
Err(err) => {
|
||||||
|
bail!("Error loading .npmrc at {}. {:#}", path.display(), err)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(maybe_source.map(|source| (source, path)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_to_parse_npmrc(
|
||||||
|
source: String,
|
||||||
|
path: &Path,
|
||||||
|
) -> Result<Arc<ResolvedNpmRc>, AnyError> {
|
||||||
|
let npmrc = NpmRc::parse(&source, &get_env_var).with_context(|| {
|
||||||
|
format!("Failed to parse .npmrc at {}", path.display())
|
||||||
|
})?;
|
||||||
|
let resolved = npmrc
|
||||||
|
.as_resolved(npm_registry_url())
|
||||||
|
.context("Failed to resolve .npmrc options")?;
|
||||||
|
Ok(Arc::new(resolved))
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(package_json_path) = maybe_package_json_path {
|
||||||
|
if let Some(package_json_dir) = package_json_path.parent() {
|
||||||
|
if let Some((source, path)) = try_to_read_npmrc(package_json_dir)? {
|
||||||
|
return try_to_parse_npmrc(source, &path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(deno_json_path) = maybe_deno_json_path {
|
||||||
|
if let Some(deno_json_dir) = deno_json_path.parent() {
|
||||||
|
if let Some((source, path)) = try_to_read_npmrc(deno_json_dir)? {
|
||||||
|
return try_to_parse_npmrc(source, &path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::debug!("No .npmrc file found");
|
||||||
|
Ok(create_default_npmrc())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_default_npmrc() -> Arc<ResolvedNpmRc> {
|
||||||
|
Arc::new(ResolvedNpmRc {
|
||||||
|
default_config: deno_npm::npm_rc::RegistryConfigWithUrl {
|
||||||
|
registry_url: npm_registry_url().clone(),
|
||||||
|
config: Default::default(),
|
||||||
|
},
|
||||||
|
scopes: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
struct CliRootCertStoreProvider {
|
struct CliRootCertStoreProvider {
|
||||||
cell: OnceCell<RootCertStore>,
|
cell: OnceCell<RootCertStore>,
|
||||||
maybe_root_path: Option<PathBuf>,
|
maybe_root_path: Option<PathBuf>,
|
||||||
|
@ -722,6 +801,7 @@ pub struct CliOptions {
|
||||||
maybe_vendor_folder: Option<PathBuf>,
|
maybe_vendor_folder: Option<PathBuf>,
|
||||||
maybe_config_file: Option<ConfigFile>,
|
maybe_config_file: Option<ConfigFile>,
|
||||||
maybe_package_json: Option<PackageJson>,
|
maybe_package_json: Option<PackageJson>,
|
||||||
|
npmrc: Arc<ResolvedNpmRc>,
|
||||||
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
overrides: CliOptionOverrides,
|
overrides: CliOptionOverrides,
|
||||||
maybe_workspace_config: Option<WorkspaceConfig>,
|
maybe_workspace_config: Option<WorkspaceConfig>,
|
||||||
|
@ -736,6 +816,7 @@ impl CliOptions {
|
||||||
maybe_config_file: Option<ConfigFile>,
|
maybe_config_file: Option<ConfigFile>,
|
||||||
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
maybe_package_json: Option<PackageJson>,
|
maybe_package_json: Option<PackageJson>,
|
||||||
|
npmrc: Arc<ResolvedNpmRc>,
|
||||||
force_global_cache: bool,
|
force_global_cache: bool,
|
||||||
) -> Result<Self, AnyError> {
|
) -> Result<Self, AnyError> {
|
||||||
if let Some(insecure_allowlist) =
|
if let Some(insecure_allowlist) =
|
||||||
|
@ -798,6 +879,7 @@ impl CliOptions {
|
||||||
maybe_config_file,
|
maybe_config_file,
|
||||||
maybe_lockfile,
|
maybe_lockfile,
|
||||||
maybe_package_json,
|
maybe_package_json,
|
||||||
|
npmrc,
|
||||||
maybe_node_modules_folder,
|
maybe_node_modules_folder,
|
||||||
maybe_vendor_folder,
|
maybe_vendor_folder,
|
||||||
overrides: Default::default(),
|
overrides: Default::default(),
|
||||||
|
@ -851,6 +933,16 @@ impl CliOptions {
|
||||||
} else {
|
} else {
|
||||||
maybe_package_json = discover_package_json(&flags, None, &initial_cwd)?;
|
maybe_package_json = discover_package_json(&flags, None, &initial_cwd)?;
|
||||||
}
|
}
|
||||||
|
let npmrc = discover_npmrc(
|
||||||
|
maybe_package_json.as_ref().map(|p| p.path.clone()),
|
||||||
|
maybe_config_file.as_ref().and_then(|cf| {
|
||||||
|
if cf.specifier.scheme() == "file" {
|
||||||
|
Some(cf.specifier.to_file_path().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)?;
|
||||||
|
|
||||||
let maybe_lock_file = lockfile::discover(
|
let maybe_lock_file = lockfile::discover(
|
||||||
&flags,
|
&flags,
|
||||||
|
@ -863,6 +955,7 @@ impl CliOptions {
|
||||||
maybe_config_file,
|
maybe_config_file,
|
||||||
maybe_lock_file.map(|l| Arc::new(Mutex::new(l))),
|
maybe_lock_file.map(|l| Arc::new(Mutex::new(l))),
|
||||||
maybe_package_json,
|
maybe_package_json,
|
||||||
|
npmrc,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1172,6 +1265,7 @@ impl CliOptions {
|
||||||
maybe_vendor_folder: self.maybe_vendor_folder.clone(),
|
maybe_vendor_folder: self.maybe_vendor_folder.clone(),
|
||||||
maybe_config_file: self.maybe_config_file.clone(),
|
maybe_config_file: self.maybe_config_file.clone(),
|
||||||
maybe_package_json: self.maybe_package_json.clone(),
|
maybe_package_json: self.maybe_package_json.clone(),
|
||||||
|
npmrc: self.npmrc.clone(),
|
||||||
maybe_lockfile: self.maybe_lockfile.clone(),
|
maybe_lockfile: self.maybe_lockfile.clone(),
|
||||||
maybe_workspace_config: self.maybe_workspace_config.clone(),
|
maybe_workspace_config: self.maybe_workspace_config.clone(),
|
||||||
overrides: self.overrides.clone(),
|
overrides: self.overrides.clone(),
|
||||||
|
@ -1303,6 +1397,10 @@ impl CliOptions {
|
||||||
&self.maybe_package_json
|
&self.maybe_package_json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn npmrc(&self) -> &Arc<ResolvedNpmRc> {
|
||||||
|
&self.npmrc
|
||||||
|
}
|
||||||
|
|
||||||
pub fn maybe_package_json_deps(&self) -> Option<PackageJsonDeps> {
|
pub fn maybe_package_json_deps(&self) -> Option<PackageJsonDeps> {
|
||||||
if matches!(
|
if matches!(
|
||||||
self.flags.subcommand,
|
self.flags.subcommand,
|
||||||
|
|
|
@ -446,7 +446,7 @@ impl CliFactory {
|
||||||
self.package_json_deps_provider().clone(),
|
self.package_json_deps_provider().clone(),
|
||||||
),
|
),
|
||||||
npm_system_info: self.options.npm_system_info(),
|
npm_system_info: self.options.npm_system_info(),
|
||||||
npm_registry_url: crate::args::npm_registry_url().to_owned(),
|
npmrc: self.options.npmrc().clone()
|
||||||
})
|
})
|
||||||
}).await
|
}).await
|
||||||
}.boxed_local())
|
}.boxed_local())
|
||||||
|
|
|
@ -17,6 +17,8 @@ use deno_runtime::deno_fetch::reqwest::header::LOCATION;
|
||||||
use deno_runtime::deno_fetch::reqwest::Response;
|
use deno_runtime::deno_fetch::reqwest::Response;
|
||||||
use deno_runtime::deno_fetch::CreateHttpClientOptions;
|
use deno_runtime::deno_fetch::CreateHttpClientOptions;
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
|
use reqwest::header::HeaderName;
|
||||||
|
use reqwest::header::HeaderValue;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -294,7 +296,7 @@ impl HttpClient {
|
||||||
&self,
|
&self,
|
||||||
url: U,
|
url: U,
|
||||||
) -> Result<Vec<u8>, AnyError> {
|
) -> Result<Vec<u8>, AnyError> {
|
||||||
let maybe_bytes = self.inner_download(url, None).await?;
|
let maybe_bytes = self.inner_download(url, None, None).await?;
|
||||||
match maybe_bytes {
|
match maybe_bytes {
|
||||||
Some(bytes) => Ok(bytes),
|
Some(bytes) => Ok(bytes),
|
||||||
None => Err(custom_error("Http", "Not found.")),
|
None => Err(custom_error("Http", "Not found.")),
|
||||||
|
@ -304,17 +306,21 @@ impl HttpClient {
|
||||||
pub async fn download_with_progress<U: reqwest::IntoUrl>(
|
pub async fn download_with_progress<U: reqwest::IntoUrl>(
|
||||||
&self,
|
&self,
|
||||||
url: U,
|
url: U,
|
||||||
|
maybe_header: Option<(HeaderName, HeaderValue)>,
|
||||||
progress_guard: &UpdateGuard,
|
progress_guard: &UpdateGuard,
|
||||||
) -> Result<Option<Vec<u8>>, AnyError> {
|
) -> Result<Option<Vec<u8>>, AnyError> {
|
||||||
self.inner_download(url, Some(progress_guard)).await
|
self
|
||||||
|
.inner_download(url, maybe_header, Some(progress_guard))
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inner_download<U: reqwest::IntoUrl>(
|
async fn inner_download<U: reqwest::IntoUrl>(
|
||||||
&self,
|
&self,
|
||||||
url: U,
|
url: U,
|
||||||
|
maybe_header: Option<(HeaderName, HeaderValue)>,
|
||||||
progress_guard: Option<&UpdateGuard>,
|
progress_guard: Option<&UpdateGuard>,
|
||||||
) -> Result<Option<Vec<u8>>, AnyError> {
|
) -> Result<Option<Vec<u8>>, AnyError> {
|
||||||
let response = self.get_redirected_response(url).await?;
|
let response = self.get_redirected_response(url, maybe_header).await?;
|
||||||
|
|
||||||
if response.status() == 404 {
|
if response.status() == 404 {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
@ -339,15 +345,30 @@ impl HttpClient {
|
||||||
pub async fn get_redirected_response<U: reqwest::IntoUrl>(
|
pub async fn get_redirected_response<U: reqwest::IntoUrl>(
|
||||||
&self,
|
&self,
|
||||||
url: U,
|
url: U,
|
||||||
|
mut maybe_header: Option<(HeaderName, HeaderValue)>,
|
||||||
) -> Result<Response, AnyError> {
|
) -> Result<Response, AnyError> {
|
||||||
let mut url = url.into_url()?;
|
let mut url = url.into_url()?;
|
||||||
let mut response = self.get_no_redirect(url.clone())?.send().await?;
|
|
||||||
|
let mut builder = self.get_no_redirect(url.clone())?;
|
||||||
|
if let Some((header_name, header_value)) = maybe_header.as_ref() {
|
||||||
|
builder = builder.header(header_name, header_value);
|
||||||
|
}
|
||||||
|
let mut response = builder.send().await?;
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
if status.is_redirection() {
|
if status.is_redirection() {
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
let new_url = resolve_redirect_from_response(&url, &response)?;
|
let new_url = resolve_redirect_from_response(&url, &response)?;
|
||||||
let new_response =
|
let mut builder = self.get_no_redirect(new_url.clone())?;
|
||||||
self.get_no_redirect(new_url.clone())?.send().await?;
|
|
||||||
|
if new_url.origin() == url.origin() {
|
||||||
|
if let Some((header_name, header_value)) = maybe_header.as_ref() {
|
||||||
|
builder = builder.header(header_name, header_value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maybe_header = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_response = builder.send().await?;
|
||||||
let status = new_response.status();
|
let status = new_response.status();
|
||||||
if status.is_redirection() {
|
if status.is_redirection() {
|
||||||
response = new_response;
|
response = new_response;
|
||||||
|
|
|
@ -24,6 +24,7 @@ use deno_core::serde_json::json;
|
||||||
use deno_core::serde_json::Value;
|
use deno_core::serde_json::Value;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_lockfile::Lockfile;
|
use deno_lockfile::Lockfile;
|
||||||
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_runtime::fs_util::specifier_to_file_path;
|
use deno_runtime::fs_util::specifier_to_file_path;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
|
@ -1090,6 +1091,7 @@ pub struct ConfigData {
|
||||||
pub vendor_dir: Option<PathBuf>,
|
pub vendor_dir: Option<PathBuf>,
|
||||||
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
pub package_json: Option<Arc<PackageJson>>,
|
pub package_json: Option<Arc<PackageJson>>,
|
||||||
|
pub npmrc: Option<Arc<ResolvedNpmRc>>,
|
||||||
pub import_map: Option<Arc<ImportMap>>,
|
pub import_map: Option<Arc<ImportMap>>,
|
||||||
pub import_map_from_settings: bool,
|
pub import_map_from_settings: bool,
|
||||||
watched_files: HashMap<ModuleSpecifier, ConfigWatchedFileType>,
|
watched_files: HashMap<ModuleSpecifier, ConfigWatchedFileType>,
|
||||||
|
@ -1274,6 +1276,8 @@ impl ConfigData {
|
||||||
|
|
||||||
// Load package.json
|
// Load package.json
|
||||||
let mut package_json = None;
|
let mut package_json = None;
|
||||||
|
// TODO(bartlomieju): support discovering .npmrc
|
||||||
|
let npmrc = None;
|
||||||
if let Ok(path) = specifier_to_file_path(scope) {
|
if let Ok(path) = specifier_to_file_path(scope) {
|
||||||
let path = path.join("package.json");
|
let path = path.join("package.json");
|
||||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(&path) {
|
if let Ok(specifier) = ModuleSpecifier::from_file_path(&path) {
|
||||||
|
@ -1429,6 +1433,7 @@ impl ConfigData {
|
||||||
vendor_dir,
|
vendor_dir,
|
||||||
lockfile: lockfile.map(Mutex::new).map(Arc::new),
|
lockfile: lockfile.map(Mutex::new).map(Arc::new),
|
||||||
package_json: package_json.map(Arc::new),
|
package_json: package_json.map(Arc::new),
|
||||||
|
npmrc: npmrc.map(Arc::new),
|
||||||
import_map: import_map.map(Arc::new),
|
import_map: import_map.map(Arc::new),
|
||||||
import_map_from_settings,
|
import_map_from_settings,
|
||||||
watched_files,
|
watched_files,
|
||||||
|
|
|
@ -83,6 +83,7 @@ use super::tsc::ChangeKind;
|
||||||
use super::tsc::GetCompletionDetailsArgs;
|
use super::tsc::GetCompletionDetailsArgs;
|
||||||
use super::tsc::TsServer;
|
use super::tsc::TsServer;
|
||||||
use super::urls;
|
use super::urls;
|
||||||
|
use crate::args::create_default_npmrc;
|
||||||
use crate::args::get_root_cert_store;
|
use crate::args::get_root_cert_store;
|
||||||
use crate::args::CaData;
|
use crate::args::CaData;
|
||||||
use crate::args::CacheSetting;
|
use crate::args::CacheSetting;
|
||||||
|
@ -3318,6 +3319,9 @@ impl Inner {
|
||||||
config_data.and_then(|d| d.config_file.as_deref().cloned()),
|
config_data.and_then(|d| d.config_file.as_deref().cloned()),
|
||||||
config_data.and_then(|d| d.lockfile.clone()),
|
config_data.and_then(|d| d.lockfile.clone()),
|
||||||
config_data.and_then(|d| d.package_json.as_deref().cloned()),
|
config_data.and_then(|d| d.package_json.as_deref().cloned()),
|
||||||
|
config_data
|
||||||
|
.and_then(|d| d.npmrc.clone())
|
||||||
|
.unwrap_or_else(create_default_npmrc),
|
||||||
force_global_cache,
|
force_global_cache,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use crate::args::create_default_npmrc;
|
||||||
use crate::args::package_json;
|
use crate::args::package_json;
|
||||||
use crate::args::CacheSetting;
|
use crate::args::CacheSetting;
|
||||||
use crate::cache::FastInsecureHasher;
|
use crate::cache::FastInsecureHasher;
|
||||||
|
@ -363,7 +364,10 @@ async fn create_npm_resolver(
|
||||||
// do not install while resolving in the lsp—leave that to the cache command
|
// do not install while resolving in the lsp—leave that to the cache command
|
||||||
package_json_installer:
|
package_json_installer:
|
||||||
CliNpmResolverManagedPackageJsonInstallerOption::NoInstall,
|
CliNpmResolverManagedPackageJsonInstallerOption::NoInstall,
|
||||||
npm_registry_url: crate::args::npm_registry_url().to_owned(),
|
npmrc: config_data
|
||||||
|
.npmrc
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(create_default_npmrc),
|
||||||
npm_system_info: NpmSystemInfo::default(),
|
npm_system_info: NpmSystemInfo::default(),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,10 +20,13 @@ pub struct NpmCacheDir {
|
||||||
root_dir: PathBuf,
|
root_dir: PathBuf,
|
||||||
// cached url representation of the root directory
|
// cached url representation of the root directory
|
||||||
root_dir_url: Url,
|
root_dir_url: Url,
|
||||||
|
// A list of all registry that were discovered via `.npmrc` files
|
||||||
|
// turned into a safe directory names.
|
||||||
|
known_registries_dirnames: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NpmCacheDir {
|
impl NpmCacheDir {
|
||||||
pub fn new(root_dir: PathBuf) -> Self {
|
pub fn new(root_dir: PathBuf, known_registries_urls: Vec<Url>) -> Self {
|
||||||
fn try_get_canonicalized_root_dir(
|
fn try_get_canonicalized_root_dir(
|
||||||
root_dir: &Path,
|
root_dir: &Path,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
|
@ -38,12 +41,27 @@ impl NpmCacheDir {
|
||||||
let root_dir =
|
let root_dir =
|
||||||
try_get_canonicalized_root_dir(&root_dir).unwrap_or(root_dir);
|
try_get_canonicalized_root_dir(&root_dir).unwrap_or(root_dir);
|
||||||
let root_dir_url = Url::from_directory_path(&root_dir).unwrap();
|
let root_dir_url = Url::from_directory_path(&root_dir).unwrap();
|
||||||
|
|
||||||
|
let known_registries_dirnames: Vec<_> = known_registries_urls
|
||||||
|
.into_iter()
|
||||||
|
.map(|url| {
|
||||||
|
root_url_to_safe_local_dirname(&url)
|
||||||
|
.to_string_lossy()
|
||||||
|
.replace('\\', "/")
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
root_dir,
|
root_dir,
|
||||||
root_dir_url,
|
root_dir_url,
|
||||||
|
known_registries_dirnames,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn root_dir(&self) -> &Path {
|
||||||
|
&self.root_dir
|
||||||
|
}
|
||||||
|
|
||||||
pub fn root_dir_url(&self) -> &Url {
|
pub fn root_dir_url(&self) -> &Url {
|
||||||
&self.root_dir_url
|
&self.root_dir_url
|
||||||
}
|
}
|
||||||
|
@ -88,7 +106,7 @@ impl NpmCacheDir {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn registry_folder(&self, registry_url: &Url) -> PathBuf {
|
fn registry_folder(&self, registry_url: &Url) -> PathBuf {
|
||||||
self
|
self
|
||||||
.root_dir
|
.root_dir
|
||||||
.join(root_url_to_safe_local_dirname(registry_url))
|
.join(root_url_to_safe_local_dirname(registry_url))
|
||||||
|
@ -97,23 +115,32 @@ impl NpmCacheDir {
|
||||||
pub fn resolve_package_folder_id_from_specifier(
|
pub fn resolve_package_folder_id_from_specifier(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
registry_url: &Url,
|
|
||||||
) -> Option<NpmPackageCacheFolderId> {
|
) -> Option<NpmPackageCacheFolderId> {
|
||||||
|
let mut maybe_relative_url = None;
|
||||||
|
|
||||||
|
// Iterate through known registries and try to get a match.
|
||||||
|
for registry_dirname in &self.known_registries_dirnames {
|
||||||
let registry_root_dir = self
|
let registry_root_dir = self
|
||||||
.root_dir_url
|
.root_dir_url
|
||||||
.join(&format!(
|
.join(&format!("{}/", registry_dirname))
|
||||||
"{}/",
|
|
||||||
root_url_to_safe_local_dirname(registry_url)
|
|
||||||
.to_string_lossy()
|
|
||||||
.replace('\\', "/")
|
|
||||||
))
|
|
||||||
// this not succeeding indicates a fatal issue, so unwrap
|
// this not succeeding indicates a fatal issue, so unwrap
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut relative_url = registry_root_dir.make_relative(specifier)?;
|
|
||||||
|
let Some(relative_url) = registry_root_dir.make_relative(specifier)
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
if relative_url.starts_with("../") {
|
if relative_url.starts_with("../") {
|
||||||
return None;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybe_relative_url = Some(relative_url);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut relative_url = maybe_relative_url?;
|
||||||
|
|
||||||
// base32 decode the url if it starts with an underscore
|
// base32 decode the url if it starts with an underscore
|
||||||
// * Ex. _{base32(package_name)}/
|
// * Ex. _{base32(package_name)}/
|
||||||
if let Some(end_url) = relative_url.strip_prefix('_') {
|
if let Some(end_url) = relative_url.strip_prefix('_') {
|
||||||
|
@ -194,8 +221,8 @@ mod test {
|
||||||
fn should_get_package_folder() {
|
fn should_get_package_folder() {
|
||||||
let deno_dir = crate::cache::DenoDir::new(None).unwrap();
|
let deno_dir = crate::cache::DenoDir::new(None).unwrap();
|
||||||
let root_dir = deno_dir.npm_folder_path();
|
let root_dir = deno_dir.npm_folder_path();
|
||||||
let cache = NpmCacheDir::new(root_dir.clone());
|
|
||||||
let registry_url = Url::parse("https://registry.npmjs.org/").unwrap();
|
let registry_url = Url::parse("https://registry.npmjs.org/").unwrap();
|
||||||
|
let cache = NpmCacheDir::new(root_dir.clone(), vec![registry_url.clone()]);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.package_folder_for_id(
|
cache.package_folder_for_id(
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use deno_npm::npm_rc::RegistryConfig;
|
||||||
|
use reqwest::header;
|
||||||
|
|
||||||
/// Gets the corresponding @types package for the provided package name.
|
/// Gets the corresponding @types package for the provided package name.
|
||||||
pub fn types_package_name(package_name: &str) -> String {
|
pub fn types_package_name(package_name: &str) -> String {
|
||||||
debug_assert!(!package_name.starts_with("@types/"));
|
debug_assert!(!package_name.starts_with("@types/"));
|
||||||
|
@ -8,6 +11,27 @@ pub fn types_package_name(package_name: &str) -> String {
|
||||||
format!("@types/{}", package_name.replace('/', "__"))
|
format!("@types/{}", package_name.replace('/', "__"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(bartlomieju): support more auth methods besides token and basic auth
|
||||||
|
pub fn maybe_auth_header_for_npm_registry(
|
||||||
|
registry_config: &RegistryConfig,
|
||||||
|
) -> Option<(header::HeaderName, header::HeaderValue)> {
|
||||||
|
if let Some(token) = registry_config.auth_token.as_ref() {
|
||||||
|
return Some((
|
||||||
|
header::AUTHORIZATION,
|
||||||
|
header::HeaderValue::from_str(&format!("Bearer {}", token)).unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(auth) = registry_config.auth.as_ref() {
|
||||||
|
return Some((
|
||||||
|
header::AUTHORIZATION,
|
||||||
|
header::HeaderValue::from_str(&format!("Basic {}", auth)).unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::types_package_name;
|
use super::types_package_name;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use deno_core::error::custom_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_npm::registry::NpmPackageVersionDistInfo;
|
use deno_npm::registry::NpmPackageVersionDistInfo;
|
||||||
use deno_npm::NpmPackageCacheFolderId;
|
use deno_npm::NpmPackageCacheFolderId;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
|
@ -20,6 +21,7 @@ use deno_semver::package::PackageNv;
|
||||||
|
|
||||||
use crate::args::CacheSetting;
|
use crate::args::CacheSetting;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
|
use crate::npm::common::maybe_auth_header_for_npm_registry;
|
||||||
use crate::npm::NpmCacheDir;
|
use crate::npm::NpmCacheDir;
|
||||||
use crate::util::fs::hard_link_dir_recursive;
|
use crate::util::fs::hard_link_dir_recursive;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
|
@ -35,6 +37,7 @@ pub struct NpmCache {
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
http_client: Arc<HttpClient>,
|
http_client: Arc<HttpClient>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
|
pub(crate) npmrc: Arc<ResolvedNpmRc>,
|
||||||
/// ensures a package is only downloaded once per run
|
/// ensures a package is only downloaded once per run
|
||||||
previously_reloaded_packages: Mutex<HashSet<PackageNv>>,
|
previously_reloaded_packages: Mutex<HashSet<PackageNv>>,
|
||||||
}
|
}
|
||||||
|
@ -46,6 +49,7 @@ impl NpmCache {
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
http_client: Arc<HttpClient>,
|
http_client: Arc<HttpClient>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
|
npmrc: Arc<ResolvedNpmRc>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cache_dir,
|
cache_dir,
|
||||||
|
@ -54,6 +58,7 @@ impl NpmCache {
|
||||||
http_client,
|
http_client,
|
||||||
progress_bar,
|
progress_bar,
|
||||||
previously_reloaded_packages: Default::default(),
|
previously_reloaded_packages: Default::default(),
|
||||||
|
npmrc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,10 +87,9 @@ impl NpmCache {
|
||||||
&self,
|
&self,
|
||||||
package: &PackageNv,
|
package: &PackageNv,
|
||||||
dist: &NpmPackageVersionDistInfo,
|
dist: &NpmPackageVersionDistInfo,
|
||||||
registry_url: &Url,
|
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self
|
self
|
||||||
.ensure_package_inner(package, dist, registry_url)
|
.ensure_package_inner(package, dist)
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("Failed caching npm package '{package}'."))
|
.with_context(|| format!("Failed caching npm package '{package}'."))
|
||||||
}
|
}
|
||||||
|
@ -94,8 +98,10 @@ impl NpmCache {
|
||||||
&self,
|
&self,
|
||||||
package_nv: &PackageNv,
|
package_nv: &PackageNv,
|
||||||
dist: &NpmPackageVersionDistInfo,
|
dist: &NpmPackageVersionDistInfo,
|
||||||
registry_url: &Url,
|
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
|
let registry_url = self.npmrc.get_registry_url(&package_nv.name);
|
||||||
|
let registry_config = self.npmrc.get_registry_config(&package_nv.name);
|
||||||
|
|
||||||
let package_folder = self
|
let package_folder = self
|
||||||
.cache_dir
|
.cache_dir
|
||||||
.package_folder_for_name_and_version(package_nv, registry_url);
|
.package_folder_for_name_and_version(package_nv, registry_url);
|
||||||
|
@ -118,10 +124,12 @@ impl NpmCache {
|
||||||
bail!("Tarball URL was empty.");
|
bail!("Tarball URL was empty.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let maybe_auth_header = maybe_auth_header_for_npm_registry(registry_config);
|
||||||
|
|
||||||
let guard = self.progress_bar.update(&dist.tarball);
|
let guard = self.progress_bar.update(&dist.tarball);
|
||||||
let maybe_bytes = self
|
let maybe_bytes = self
|
||||||
.http_client
|
.http_client
|
||||||
.download_with_progress(&dist.tarball, &guard)
|
.download_with_progress(&dist.tarball, maybe_auth_header, &guard)
|
||||||
.await?;
|
.await?;
|
||||||
match maybe_bytes {
|
match maybe_bytes {
|
||||||
Some(bytes) => {
|
Some(bytes) => {
|
||||||
|
@ -164,8 +172,8 @@ impl NpmCache {
|
||||||
pub fn ensure_copy_package(
|
pub fn ensure_copy_package(
|
||||||
&self,
|
&self,
|
||||||
folder_id: &NpmPackageCacheFolderId,
|
folder_id: &NpmPackageCacheFolderId,
|
||||||
registry_url: &Url,
|
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
|
let registry_url = self.npmrc.get_registry_url(&folder_id.nv.name);
|
||||||
assert_ne!(folder_id.copy_index, 0);
|
assert_ne!(folder_id.copy_index, 0);
|
||||||
let package_folder = self
|
let package_folder = self
|
||||||
.cache_dir
|
.cache_dir
|
||||||
|
@ -192,40 +200,37 @@ impl NpmCache {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn package_folder_for_id(
|
pub fn package_folder_for_id(&self, id: &NpmPackageCacheFolderId) -> PathBuf {
|
||||||
&self,
|
let registry_url = self.npmrc.get_registry_url(&id.nv.name);
|
||||||
id: &NpmPackageCacheFolderId,
|
|
||||||
registry_url: &Url,
|
|
||||||
) -> PathBuf {
|
|
||||||
self.cache_dir.package_folder_for_id(id, registry_url)
|
self.cache_dir.package_folder_for_id(id, registry_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn package_folder_for_name_and_version(
|
pub fn package_folder_for_name_and_version(
|
||||||
&self,
|
&self,
|
||||||
package: &PackageNv,
|
package: &PackageNv,
|
||||||
registry_url: &Url,
|
|
||||||
) -> PathBuf {
|
) -> PathBuf {
|
||||||
|
let registry_url = self.npmrc.get_registry_url(&package.name);
|
||||||
self
|
self
|
||||||
.cache_dir
|
.cache_dir
|
||||||
.package_folder_for_name_and_version(package, registry_url)
|
.package_folder_for_name_and_version(package, registry_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn package_name_folder(&self, name: &str, registry_url: &Url) -> PathBuf {
|
pub fn package_name_folder(&self, name: &str) -> PathBuf {
|
||||||
|
let registry_url = self.npmrc.get_registry_url(name);
|
||||||
self.cache_dir.package_name_folder(name, registry_url)
|
self.cache_dir.package_name_folder(name, registry_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn registry_folder(&self, registry_url: &Url) -> PathBuf {
|
pub fn root_folder(&self) -> PathBuf {
|
||||||
self.cache_dir.registry_folder(registry_url)
|
self.cache_dir.root_dir().to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_package_folder_id_from_specifier(
|
pub fn resolve_package_folder_id_from_specifier(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
registry_url: &Url,
|
|
||||||
) -> Option<NpmPackageCacheFolderId> {
|
) -> Option<NpmPackageCacheFolderId> {
|
||||||
self
|
self
|
||||||
.cache_dir
|
.cache_dir
|
||||||
.resolve_package_folder_id_from_specifier(specifier, registry_url)
|
.resolve_package_folder_id_from_specifier(specifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::url::Url;
|
|
||||||
use deno_graph::NpmPackageReqResolution;
|
use deno_graph::NpmPackageReqResolution;
|
||||||
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_npm::registry::NpmRegistryApi;
|
use deno_npm::registry::NpmRegistryApi;
|
||||||
use deno_npm::resolution::NpmResolutionSnapshot;
|
use deno_npm::resolution::NpmResolutionSnapshot;
|
||||||
use deno_npm::resolution::PackageReqNotFoundError;
|
use deno_npm::resolution::PackageReqNotFoundError;
|
||||||
|
@ -72,7 +72,7 @@ pub struct CliNpmResolverManagedCreateOptions {
|
||||||
pub maybe_node_modules_path: Option<PathBuf>,
|
pub maybe_node_modules_path: Option<PathBuf>,
|
||||||
pub npm_system_info: NpmSystemInfo,
|
pub npm_system_info: NpmSystemInfo,
|
||||||
pub package_json_installer: CliNpmResolverManagedPackageJsonInstallerOption,
|
pub package_json_installer: CliNpmResolverManagedPackageJsonInstallerOption,
|
||||||
pub npm_registry_url: Url,
|
pub npmrc: Arc<ResolvedNpmRc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_managed_npm_resolver_for_lsp(
|
pub async fn create_managed_npm_resolver_for_lsp(
|
||||||
|
@ -96,7 +96,6 @@ pub async fn create_managed_npm_resolver_for_lsp(
|
||||||
options.text_only_progress_bar,
|
options.text_only_progress_bar,
|
||||||
options.maybe_node_modules_path,
|
options.maybe_node_modules_path,
|
||||||
options.package_json_installer,
|
options.package_json_installer,
|
||||||
options.npm_registry_url,
|
|
||||||
options.npm_system_info,
|
options.npm_system_info,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +115,6 @@ pub async fn create_managed_npm_resolver(
|
||||||
options.text_only_progress_bar,
|
options.text_only_progress_bar,
|
||||||
options.maybe_node_modules_path,
|
options.maybe_node_modules_path,
|
||||||
options.package_json_installer,
|
options.package_json_installer,
|
||||||
options.npm_registry_url,
|
|
||||||
options.npm_system_info,
|
options.npm_system_info,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -131,7 +129,6 @@ fn create_inner(
|
||||||
text_only_progress_bar: crate::util::progress_bar::ProgressBar,
|
text_only_progress_bar: crate::util::progress_bar::ProgressBar,
|
||||||
node_modules_dir_path: Option<PathBuf>,
|
node_modules_dir_path: Option<PathBuf>,
|
||||||
package_json_installer: CliNpmResolverManagedPackageJsonInstallerOption,
|
package_json_installer: CliNpmResolverManagedPackageJsonInstallerOption,
|
||||||
npm_registry_url: Url,
|
|
||||||
npm_system_info: NpmSystemInfo,
|
npm_system_info: NpmSystemInfo,
|
||||||
) -> Arc<dyn CliNpmResolver> {
|
) -> Arc<dyn CliNpmResolver> {
|
||||||
let resolution = Arc::new(NpmResolution::from_serialized(
|
let resolution = Arc::new(NpmResolution::from_serialized(
|
||||||
|
@ -143,7 +140,6 @@ fn create_inner(
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
npm_cache.clone(),
|
npm_cache.clone(),
|
||||||
&text_only_progress_bar,
|
&text_only_progress_bar,
|
||||||
npm_registry_url,
|
|
||||||
resolution.clone(),
|
resolution.clone(),
|
||||||
node_modules_dir_path,
|
node_modules_dir_path,
|
||||||
npm_system_info.clone(),
|
npm_system_info.clone(),
|
||||||
|
@ -175,11 +171,15 @@ fn create_inner(
|
||||||
|
|
||||||
fn create_cache(options: &CliNpmResolverManagedCreateOptions) -> Arc<NpmCache> {
|
fn create_cache(options: &CliNpmResolverManagedCreateOptions) -> Arc<NpmCache> {
|
||||||
Arc::new(NpmCache::new(
|
Arc::new(NpmCache::new(
|
||||||
NpmCacheDir::new(options.npm_global_cache_dir.clone()),
|
NpmCacheDir::new(
|
||||||
|
options.npm_global_cache_dir.clone(),
|
||||||
|
options.npmrc.get_all_known_registries_urls(),
|
||||||
|
),
|
||||||
options.cache_setting.clone(),
|
options.cache_setting.clone(),
|
||||||
options.fs.clone(),
|
options.fs.clone(),
|
||||||
options.http_client.clone(),
|
options.http_client.clone(),
|
||||||
options.text_only_progress_bar.clone(),
|
options.text_only_progress_bar.clone(),
|
||||||
|
options.npmrc.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,9 +188,9 @@ fn create_api(
|
||||||
npm_cache: Arc<NpmCache>,
|
npm_cache: Arc<NpmCache>,
|
||||||
) -> Arc<CliNpmRegistryApi> {
|
) -> Arc<CliNpmRegistryApi> {
|
||||||
Arc::new(CliNpmRegistryApi::new(
|
Arc::new(CliNpmRegistryApi::new(
|
||||||
options.npm_registry_url.clone(),
|
|
||||||
npm_cache.clone(),
|
npm_cache.clone(),
|
||||||
options.http_client.clone(),
|
options.http_client.clone(),
|
||||||
|
options.npmrc.clone(),
|
||||||
options.text_only_progress_bar.clone(),
|
options.text_only_progress_bar.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -483,15 +483,8 @@ impl ManagedCliNpmResolver {
|
||||||
.map_err(|err| err.into())
|
.map_err(|err| err.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn registry_base_url(&self) -> &ModuleSpecifier {
|
pub fn global_cache_root_folder(&self) -> PathBuf {
|
||||||
self.api.base_url()
|
self.global_npm_cache.root_folder()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn registry_folder_in_global_cache(
|
|
||||||
&self,
|
|
||||||
registry_url: &ModuleSpecifier,
|
|
||||||
) -> PathBuf {
|
|
||||||
self.global_npm_cache.registry_folder(registry_url)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,7 +557,6 @@ impl CliNpmResolver for ManagedCliNpmResolver {
|
||||||
self.fs.clone(),
|
self.fs.clone(),
|
||||||
self.global_npm_cache.clone(),
|
self.global_npm_cache.clone(),
|
||||||
&self.progress_bar,
|
&self.progress_bar,
|
||||||
self.api.base_url().clone(),
|
|
||||||
npm_resolution,
|
npm_resolution,
|
||||||
self.root_node_modules_path().map(ToOwned::to_owned),
|
self.root_node_modules_path().map(ToOwned::to_owned),
|
||||||
self.npm_system_info.clone(),
|
self.npm_system_info.clone(),
|
||||||
|
|
|
@ -18,6 +18,8 @@ use deno_core::futures::FutureExt;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
use deno_npm::npm_rc::RegistryConfig;
|
||||||
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_npm::registry::NpmPackageInfo;
|
use deno_npm::registry::NpmPackageInfo;
|
||||||
use deno_npm::registry::NpmRegistryApi;
|
use deno_npm::registry::NpmRegistryApi;
|
||||||
use deno_npm::registry::NpmRegistryPackageInfoLoadError;
|
use deno_npm::registry::NpmRegistryPackageInfoLoadError;
|
||||||
|
@ -25,6 +27,7 @@ use deno_npm::registry::NpmRegistryPackageInfoLoadError;
|
||||||
use crate::args::CacheSetting;
|
use crate::args::CacheSetting;
|
||||||
use crate::cache::CACHE_PERM;
|
use crate::cache::CACHE_PERM;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
|
use crate::npm::common::maybe_auth_header_for_npm_registry;
|
||||||
use crate::util::fs::atomic_write_file;
|
use crate::util::fs::atomic_write_file;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
use crate::util::sync::AtomicFlag;
|
use crate::util::sync::AtomicFlag;
|
||||||
|
@ -36,17 +39,17 @@ pub struct CliNpmRegistryApi(Option<Arc<CliNpmRegistryApiInner>>);
|
||||||
|
|
||||||
impl CliNpmRegistryApi {
|
impl CliNpmRegistryApi {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
base_url: Url,
|
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
http_client: Arc<HttpClient>,
|
http_client: Arc<HttpClient>,
|
||||||
|
npmrc: Arc<ResolvedNpmRc>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self(Some(Arc::new(CliNpmRegistryApiInner {
|
Self(Some(Arc::new(CliNpmRegistryApiInner {
|
||||||
base_url,
|
|
||||||
cache,
|
cache,
|
||||||
force_reload_flag: Default::default(),
|
force_reload_flag: Default::default(),
|
||||||
mem_cache: Default::default(),
|
mem_cache: Default::default(),
|
||||||
previously_reloaded_packages: Default::default(),
|
previously_reloaded_packages: Default::default(),
|
||||||
|
npmrc,
|
||||||
http_client,
|
http_client,
|
||||||
progress_bar,
|
progress_bar,
|
||||||
})))
|
})))
|
||||||
|
@ -64,10 +67,6 @@ impl CliNpmRegistryApi {
|
||||||
self.inner().get_cached_package_info(name)
|
self.inner().get_cached_package_info(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn base_url(&self) -> &Url {
|
|
||||||
&self.inner().base_url
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner(&self) -> &Arc<CliNpmRegistryApiInner> {
|
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
|
||||||
|
@ -121,12 +120,12 @@ enum CacheItem {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct CliNpmRegistryApiInner {
|
struct CliNpmRegistryApiInner {
|
||||||
base_url: Url,
|
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
force_reload_flag: AtomicFlag,
|
force_reload_flag: AtomicFlag,
|
||||||
mem_cache: Mutex<HashMap<String, CacheItem>>,
|
mem_cache: Mutex<HashMap<String, CacheItem>>,
|
||||||
previously_reloaded_packages: Mutex<HashSet<String>>,
|
previously_reloaded_packages: Mutex<HashSet<String>>,
|
||||||
http_client: Arc<HttpClient>,
|
http_client: Arc<HttpClient>,
|
||||||
|
npmrc: Arc<ResolvedNpmRc>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,13 +272,20 @@ impl CliNpmRegistryApiInner {
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Result<Option<NpmPackageInfo>, AnyError> {
|
) -> Result<Option<NpmPackageInfo>, AnyError> {
|
||||||
|
let registry_url = self.npmrc.get_registry_url(name);
|
||||||
|
let registry_config = self.npmrc.get_registry_config(name);
|
||||||
|
|
||||||
self
|
self
|
||||||
.load_package_info_from_registry_inner(name)
|
.load_package_info_from_registry_inner(
|
||||||
|
name,
|
||||||
|
registry_url,
|
||||||
|
registry_config,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"Error getting response at {} for package \"{}\"",
|
"Error getting response at {} for package \"{}\"",
|
||||||
self.get_package_url(name),
|
self.get_package_url(name, registry_url),
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -288,6 +294,8 @@ impl CliNpmRegistryApiInner {
|
||||||
async fn load_package_info_from_registry_inner(
|
async fn load_package_info_from_registry_inner(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
registry_url: &Url,
|
||||||
|
registry_config: &RegistryConfig,
|
||||||
) -> Result<Option<NpmPackageInfo>, AnyError> {
|
) -> Result<Option<NpmPackageInfo>, AnyError> {
|
||||||
if *self.cache.cache_setting() == CacheSetting::Only {
|
if *self.cache.cache_setting() == CacheSetting::Only {
|
||||||
return Err(custom_error(
|
return Err(custom_error(
|
||||||
|
@ -298,12 +306,14 @@ impl CliNpmRegistryApiInner {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let package_url = self.get_package_url(name);
|
let package_url = self.get_package_url(name, registry_url);
|
||||||
let guard = self.progress_bar.update(package_url.as_str());
|
let guard = self.progress_bar.update(package_url.as_str());
|
||||||
|
|
||||||
|
let maybe_auth_header = maybe_auth_header_for_npm_registry(registry_config);
|
||||||
|
|
||||||
let maybe_bytes = self
|
let maybe_bytes = self
|
||||||
.http_client
|
.http_client
|
||||||
.download_with_progress(package_url, &guard)
|
.download_with_progress(package_url, maybe_auth_header, &guard)
|
||||||
.await?;
|
.await?;
|
||||||
match maybe_bytes {
|
match maybe_bytes {
|
||||||
Some(bytes) => {
|
Some(bytes) => {
|
||||||
|
@ -315,7 +325,7 @@ impl CliNpmRegistryApiInner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_package_url(&self, name: &str) -> Url {
|
fn get_package_url(&self, name: &str, registry_url: &Url) -> Url {
|
||||||
// list of all characters used in npm packages:
|
// list of all characters used in npm packages:
|
||||||
// !, ', (, ), *, -, ., /, [0-9], @, [A-Za-z], _, ~
|
// !, ', (, ), *, -, ., /, [0-9], @, [A-Za-z], _, ~
|
||||||
const ASCII_SET: percent_encoding::AsciiSet =
|
const ASCII_SET: percent_encoding::AsciiSet =
|
||||||
|
@ -332,11 +342,11 @@ impl CliNpmRegistryApiInner {
|
||||||
.remove(b'_')
|
.remove(b'_')
|
||||||
.remove(b'~');
|
.remove(b'~');
|
||||||
let name = percent_encoding::utf8_percent_encode(name, &ASCII_SET);
|
let name = percent_encoding::utf8_percent_encode(name, &ASCII_SET);
|
||||||
self.base_url.join(&name.to_string()).unwrap()
|
registry_url.join(&name.to_string()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_package_file_cache_path(&self, name: &str) -> PathBuf {
|
fn get_package_file_cache_path(&self, name: &str) -> PathBuf {
|
||||||
let name_folder_path = self.cache.package_name_folder(name, &self.base_url);
|
let name_folder_path = self.cache.package_name_folder(name);
|
||||||
name_folder_path.join("registry.json")
|
name_folder_path.join("registry.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,6 @@ pub trait NpmPackageFsResolver: Send + Sync {
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
|
||||||
fn resolve_package_folder_from_specifier(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
) -> Result<Option<PathBuf>, AnyError>;
|
|
||||||
|
|
||||||
fn resolve_package_cache_folder_id_from_specifier(
|
fn resolve_package_cache_folder_id_from_specifier(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
@ -132,16 +127,12 @@ impl RegistryReadPermissionChecker {
|
||||||
pub async fn cache_packages(
|
pub async fn cache_packages(
|
||||||
packages: Vec<NpmResolutionPackage>,
|
packages: Vec<NpmResolutionPackage>,
|
||||||
cache: &Arc<NpmCache>,
|
cache: &Arc<NpmCache>,
|
||||||
registry_url: &Url,
|
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let mut handles = Vec::with_capacity(packages.len());
|
let mut handles = Vec::with_capacity(packages.len());
|
||||||
for package in packages {
|
for package in packages {
|
||||||
let cache = cache.clone();
|
let cache = cache.clone();
|
||||||
let registry_url = registry_url.clone();
|
|
||||||
let handle = spawn(async move {
|
let handle = spawn(async move {
|
||||||
cache
|
cache.ensure_package(&package.id.nv, &package.dist).await
|
||||||
.ensure_package(&package.id.nv, &package.dist, ®istry_url)
|
|
||||||
.await
|
|
||||||
});
|
});
|
||||||
handles.push(handle);
|
handles.push(handle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ use super::common::RegistryReadPermissionChecker;
|
||||||
pub struct GlobalNpmPackageResolver {
|
pub struct GlobalNpmPackageResolver {
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolution>,
|
||||||
registry_url: Url,
|
|
||||||
system_info: NpmSystemInfo,
|
system_info: NpmSystemInfo,
|
||||||
registry_read_permission_checker: RegistryReadPermissionChecker,
|
registry_read_permission_checker: RegistryReadPermissionChecker,
|
||||||
}
|
}
|
||||||
|
@ -41,18 +40,16 @@ impl GlobalNpmPackageResolver {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
fs: Arc<dyn FileSystem>,
|
fs: Arc<dyn FileSystem>,
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
registry_url: Url,
|
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolution>,
|
||||||
system_info: NpmSystemInfo,
|
system_info: NpmSystemInfo,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cache: cache.clone(),
|
cache: cache.clone(),
|
||||||
resolution,
|
resolution,
|
||||||
registry_url: registry_url.clone(),
|
|
||||||
system_info,
|
system_info,
|
||||||
registry_read_permission_checker: RegistryReadPermissionChecker::new(
|
registry_read_permission_checker: RegistryReadPermissionChecker::new(
|
||||||
fs,
|
fs,
|
||||||
cache.registry_folder(®istry_url),
|
cache.root_folder(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,11 +81,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
||||||
.resolution
|
.resolution
|
||||||
.resolve_pkg_cache_folder_id_from_pkg_id(id)
|
.resolve_pkg_cache_folder_id_from_pkg_id(id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(
|
Ok(self.cache.package_folder_for_id(&folder_id))
|
||||||
self
|
|
||||||
.cache
|
|
||||||
.package_folder_for_id(&folder_id, &self.registry_url),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_package_folder_from_package(
|
fn resolve_package_folder_from_package(
|
||||||
|
@ -99,7 +92,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
let Some(referrer_pkg_id) = self
|
let Some(referrer_pkg_id) = self
|
||||||
.cache
|
.cache
|
||||||
.resolve_package_folder_id_from_specifier(referrer, &self.registry_url)
|
.resolve_package_folder_id_from_specifier(referrer)
|
||||||
else {
|
else {
|
||||||
bail!("could not find npm package for '{}'", referrer);
|
bail!("could not find npm package for '{}'", referrer);
|
||||||
};
|
};
|
||||||
|
@ -119,32 +112,14 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
||||||
self.package_folder(&pkg.id)
|
self.package_folder(&pkg.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_package_folder_from_specifier(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
) -> Result<Option<PathBuf>, AnyError> {
|
|
||||||
let Some(pkg_folder_id) = self
|
|
||||||
.cache
|
|
||||||
.resolve_package_folder_id_from_specifier(specifier, &self.registry_url)
|
|
||||||
else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
Ok(Some(
|
|
||||||
self
|
|
||||||
.cache
|
|
||||||
.package_folder_for_id(&pkg_folder_id, &self.registry_url),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_package_cache_folder_id_from_specifier(
|
fn resolve_package_cache_folder_id_from_specifier(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Result<Option<NpmPackageCacheFolderId>, AnyError> {
|
) -> Result<Option<NpmPackageCacheFolderId>, AnyError> {
|
||||||
Ok(
|
Ok(
|
||||||
self.cache.resolve_package_folder_id_from_specifier(
|
self
|
||||||
specifier,
|
.cache
|
||||||
&self.registry_url,
|
.resolve_package_folder_id_from_specifier(specifier),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,19 +128,13 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
||||||
.resolution
|
.resolution
|
||||||
.all_system_packages_partitioned(&self.system_info);
|
.all_system_packages_partitioned(&self.system_info);
|
||||||
|
|
||||||
cache_packages(
|
cache_packages(package_partitions.packages, &self.cache).await?;
|
||||||
package_partitions.packages,
|
|
||||||
&self.cache,
|
|
||||||
&self.registry_url,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// create the copy package folders
|
// create the copy package folders
|
||||||
for copy in package_partitions.copy_packages {
|
for copy in package_partitions.copy_packages {
|
||||||
self.cache.ensure_copy_package(
|
self
|
||||||
©.get_package_cache_folder_id(),
|
.cache
|
||||||
&self.registry_url,
|
.ensure_copy_package(©.get_package_cache_folder_id())?;
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -58,7 +58,6 @@ pub struct LocalNpmPackageResolver {
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolution>,
|
||||||
registry_url: Url,
|
|
||||||
root_node_modules_path: PathBuf,
|
root_node_modules_path: PathBuf,
|
||||||
root_node_modules_url: Url,
|
root_node_modules_url: Url,
|
||||||
system_info: NpmSystemInfo,
|
system_info: NpmSystemInfo,
|
||||||
|
@ -70,7 +69,6 @@ impl LocalNpmPackageResolver {
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
registry_url: Url,
|
|
||||||
node_modules_folder: PathBuf,
|
node_modules_folder: PathBuf,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolution>,
|
||||||
system_info: NpmSystemInfo,
|
system_info: NpmSystemInfo,
|
||||||
|
@ -80,7 +78,6 @@ impl LocalNpmPackageResolver {
|
||||||
cache,
|
cache,
|
||||||
progress_bar,
|
progress_bar,
|
||||||
resolution,
|
resolution,
|
||||||
registry_url,
|
|
||||||
root_node_modules_url: Url::from_directory_path(&node_modules_folder)
|
root_node_modules_url: Url::from_directory_path(&node_modules_folder)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
root_node_modules_path: node_modules_folder.clone(),
|
root_node_modules_path: node_modules_folder.clone(),
|
||||||
|
@ -126,6 +123,17 @@ impl LocalNpmPackageResolver {
|
||||||
.map(Some)
|
.map(Some)
|
||||||
.map_err(|err| err.into())
|
.map_err(|err| err.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_package_folder_from_specifier(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Result<Option<PathBuf>, AnyError> {
|
||||||
|
let Some(local_path) = self.resolve_folder_for_specifier(specifier)? else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
let package_root_path = self.resolve_package_root(&local_path);
|
||||||
|
Ok(Some(package_root_path))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -202,17 +210,6 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_package_folder_from_specifier(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
) -> Result<Option<PathBuf>, AnyError> {
|
|
||||||
let Some(local_path) = self.resolve_folder_for_specifier(specifier)? else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
let package_root_path = self.resolve_package_root(&local_path);
|
|
||||||
Ok(Some(package_root_path))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_package_cache_folder_id_from_specifier(
|
fn resolve_package_cache_folder_id_from_specifier(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
@ -231,7 +228,6 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
||||||
&self.resolution.snapshot(),
|
&self.resolution.snapshot(),
|
||||||
&self.cache,
|
&self.cache,
|
||||||
&self.progress_bar,
|
&self.progress_bar,
|
||||||
&self.registry_url,
|
|
||||||
&self.root_node_modules_path,
|
&self.root_node_modules_path,
|
||||||
&self.system_info,
|
&self.system_info,
|
||||||
)
|
)
|
||||||
|
@ -254,7 +250,6 @@ async fn sync_resolution_with_fs(
|
||||||
snapshot: &NpmResolutionSnapshot,
|
snapshot: &NpmResolutionSnapshot,
|
||||||
cache: &Arc<NpmCache>,
|
cache: &Arc<NpmCache>,
|
||||||
progress_bar: &ProgressBar,
|
progress_bar: &ProgressBar,
|
||||||
registry_url: &Url,
|
|
||||||
root_node_modules_dir_path: &Path,
|
root_node_modules_dir_path: &Path,
|
||||||
system_info: &NpmSystemInfo,
|
system_info: &NpmSystemInfo,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
|
@ -317,12 +312,9 @@ async fn sync_resolution_with_fs(
|
||||||
|
|
||||||
let pb = progress_bar.clone();
|
let pb = progress_bar.clone();
|
||||||
let cache = cache.clone();
|
let cache = cache.clone();
|
||||||
let registry_url = registry_url.clone();
|
|
||||||
let package = package.clone();
|
let package = package.clone();
|
||||||
let handle = spawn(async move {
|
let handle = spawn(async move {
|
||||||
cache
|
cache.ensure_package(&package.id.nv, &package.dist).await?;
|
||||||
.ensure_package(&package.id.nv, &package.dist, ®istry_url)
|
|
||||||
.await?;
|
|
||||||
let pb_guard = pb.update_with_prompt(
|
let pb_guard = pb.update_with_prompt(
|
||||||
ProgressMessagePrompt::Initialize,
|
ProgressMessagePrompt::Initialize,
|
||||||
&package.id.nv.to_string(),
|
&package.id.nv.to_string(),
|
||||||
|
@ -332,8 +324,8 @@ async fn sync_resolution_with_fs(
|
||||||
join_package_name(&sub_node_modules, &package.id.nv.name);
|
join_package_name(&sub_node_modules, &package.id.nv.name);
|
||||||
fs::create_dir_all(&package_path)
|
fs::create_dir_all(&package_path)
|
||||||
.with_context(|| format!("Creating '{}'", folder_path.display()))?;
|
.with_context(|| format!("Creating '{}'", folder_path.display()))?;
|
||||||
let cache_folder = cache
|
let cache_folder =
|
||||||
.package_folder_for_name_and_version(&package.id.nv, ®istry_url);
|
cache.package_folder_for_name_and_version(&package.id.nv);
|
||||||
if hard_link_dir_recursive(&cache_folder, &package_path).is_err() {
|
if hard_link_dir_recursive(&cache_folder, &package_path).is_err() {
|
||||||
// Fallback to copying the directory.
|
// Fallback to copying the directory.
|
||||||
//
|
//
|
||||||
|
|
|
@ -7,7 +7,6 @@ mod local;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::url::Url;
|
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
|
|
||||||
|
@ -25,7 +24,6 @@ pub fn create_npm_fs_resolver(
|
||||||
fs: Arc<dyn FileSystem>,
|
fs: Arc<dyn FileSystem>,
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
progress_bar: &ProgressBar,
|
progress_bar: &ProgressBar,
|
||||||
registry_url: Url,
|
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolution>,
|
||||||
maybe_node_modules_path: Option<PathBuf>,
|
maybe_node_modules_path: Option<PathBuf>,
|
||||||
system_info: NpmSystemInfo,
|
system_info: NpmSystemInfo,
|
||||||
|
@ -35,7 +33,6 @@ pub fn create_npm_fs_resolver(
|
||||||
fs,
|
fs,
|
||||||
cache,
|
cache,
|
||||||
progress_bar.clone(),
|
progress_bar.clone(),
|
||||||
registry_url,
|
|
||||||
node_modules_folder,
|
node_modules_folder,
|
||||||
resolution,
|
resolution,
|
||||||
system_info,
|
system_info,
|
||||||
|
@ -43,7 +40,6 @@ pub fn create_npm_fs_resolver(
|
||||||
None => Arc::new(GlobalNpmPackageResolver::new(
|
None => Arc::new(GlobalNpmPackageResolver::new(
|
||||||
fs,
|
fs,
|
||||||
cache,
|
cache,
|
||||||
registry_url,
|
|
||||||
resolution,
|
resolution,
|
||||||
system_info,
|
system_info,
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -537,7 +537,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
|
||||||
|
|
||||||
self
|
self
|
||||||
.client
|
.client
|
||||||
.download_with_progress(download_url, &progress)
|
.download_with_progress(download_url, None, &progress)
|
||||||
.await?
|
.await?
|
||||||
};
|
};
|
||||||
let bytes = match maybe_bytes {
|
let bytes = match maybe_bytes {
|
||||||
|
@ -670,9 +670,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
|
||||||
} else {
|
} else {
|
||||||
// DO NOT include the user's registry url as it may contain credentials,
|
// DO NOT include the user's registry url as it may contain credentials,
|
||||||
// but also don't make this dependent on the registry url
|
// but also don't make this dependent on the registry url
|
||||||
let registry_url = npm_resolver.registry_base_url();
|
let root_path = npm_resolver.global_cache_root_folder();
|
||||||
let root_path =
|
|
||||||
npm_resolver.registry_folder_in_global_cache(registry_url);
|
|
||||||
let mut builder = VfsBuilder::new(root_path)?;
|
let mut builder = VfsBuilder::new(root_path)?;
|
||||||
for package in npm_resolver.all_system_packages(&self.npm_system_info)
|
for package in npm_resolver.all_system_packages(&self.npm_system_info)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use crate::args::create_default_npmrc;
|
||||||
use crate::args::get_root_cert_store;
|
use crate::args::get_root_cert_store;
|
||||||
use crate::args::npm_pkg_req_ref_to_binary_command;
|
use crate::args::npm_pkg_req_ref_to_binary_command;
|
||||||
use crate::args::CaData;
|
use crate::args::CaData;
|
||||||
|
@ -349,7 +350,8 @@ pub async fn run(
|
||||||
let root_path = std::env::temp_dir()
|
let root_path = std::env::temp_dir()
|
||||||
.join(format!("deno-compile-{}", current_exe_name))
|
.join(format!("deno-compile-{}", current_exe_name))
|
||||||
.join("node_modules");
|
.join("node_modules");
|
||||||
let npm_cache_dir = NpmCacheDir::new(root_path.clone());
|
let npm_cache_dir =
|
||||||
|
NpmCacheDir::new(root_path.clone(), vec![npm_registry_url.clone()]);
|
||||||
let npm_global_cache_dir = npm_cache_dir.get_cache_location();
|
let npm_global_cache_dir = npm_cache_dir.get_cache_location();
|
||||||
let cache_setting = CacheSetting::Only;
|
let cache_setting = CacheSetting::Only;
|
||||||
let (package_json_deps_provider, fs, npm_resolver, maybe_vfs_root) =
|
let (package_json_deps_provider, fs, npm_resolver, maybe_vfs_root) =
|
||||||
|
@ -363,7 +365,7 @@ pub async fn run(
|
||||||
let vfs_root_dir_path = if node_modules_dir {
|
let vfs_root_dir_path = if node_modules_dir {
|
||||||
root_path
|
root_path
|
||||||
} else {
|
} else {
|
||||||
npm_cache_dir.registry_folder(&npm_registry_url)
|
npm_cache_dir.root_dir().to_owned()
|
||||||
};
|
};
|
||||||
let vfs = load_npm_vfs(vfs_root_dir_path.clone())
|
let vfs = load_npm_vfs(vfs_root_dir_path.clone())
|
||||||
.context("Failed to load npm vfs.")?;
|
.context("Failed to load npm vfs.")?;
|
||||||
|
@ -392,8 +394,10 @@ pub async fn run(
|
||||||
CliNpmResolverManagedPackageJsonInstallerOption::ConditionalInstall(
|
CliNpmResolverManagedPackageJsonInstallerOption::ConditionalInstall(
|
||||||
package_json_deps_provider.clone(),
|
package_json_deps_provider.clone(),
|
||||||
),
|
),
|
||||||
npm_registry_url,
|
|
||||||
npm_system_info: Default::default(),
|
npm_system_info: Default::default(),
|
||||||
|
// Packages from different registries are already inlined in the ESZip,
|
||||||
|
// so no need to create actual `.npmrc` configuration.
|
||||||
|
npmrc: create_default_npmrc(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -448,8 +452,10 @@ pub async fn run(
|
||||||
CliNpmResolverManagedPackageJsonInstallerOption::ConditionalInstall(
|
CliNpmResolverManagedPackageJsonInstallerOption::ConditionalInstall(
|
||||||
package_json_deps_provider.clone(),
|
package_json_deps_provider.clone(),
|
||||||
),
|
),
|
||||||
npm_registry_url,
|
|
||||||
npm_system_info: Default::default(),
|
npm_system_info: Default::default(),
|
||||||
|
// Packages from different registries are already inlined in the ESZip,
|
||||||
|
// so no need to create actual `.npmrc` configuration.
|
||||||
|
npmrc: create_default_npmrc(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
@ -139,7 +139,7 @@ pub async fn infer_name_from_url(url: &Url) -> Option<String> {
|
||||||
|
|
||||||
if url.path() == "/" {
|
if url.path() == "/" {
|
||||||
let client = HttpClient::new(None, None);
|
let client = HttpClient::new(None, None);
|
||||||
if let Ok(res) = client.get_redirected_response(url.clone()).await {
|
if let Ok(res) = client.get_redirected_response(url.clone(), None).await {
|
||||||
url = res.url().clone();
|
url = res.url().clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -619,7 +619,7 @@ async fn download_package(
|
||||||
// text above which will stay alive after the progress bars are complete
|
// text above which will stay alive after the progress bars are complete
|
||||||
let progress = progress_bar.update("");
|
let progress = progress_bar.update("");
|
||||||
client
|
client
|
||||||
.download_with_progress(download_url, &progress)
|
.download_with_progress(download_url, None, &progress)
|
||||||
.await?
|
.await?
|
||||||
};
|
};
|
||||||
match maybe_bytes {
|
match maybe_bytes {
|
||||||
|
|
|
@ -3088,7 +3088,7 @@ async fn test_private_npm_registry() {
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
let url = Url::parse("http://127.0.0.1:4261/@denotest2/basic").unwrap();
|
let url = Url::parse("http://127.0.0.1:4261/@denotest/basic").unwrap();
|
||||||
|
|
||||||
let req = reqwest::Request::new(reqwest::Method::GET, url.clone());
|
let req = reqwest::Request::new(reqwest::Method::GET, url.clone());
|
||||||
let resp = client.execute(req).await.unwrap();
|
let resp = client.execute(req).await.unwrap();
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"name": "@denotest/basic",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"main": "main.mjs",
|
||||||
|
"types": "main.d.mts"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export declare function setValue(val: number): void;
|
||||||
|
export declare function getValue(): number;
|
||||||
|
export declare const url: string;
|
11
tests/registry/npm-private2/@denotest2/basic/1.0.0/main.mjs
Normal file
11
tests/registry/npm-private2/@denotest2/basic/1.0.0/main.mjs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
let value = 0;
|
||||||
|
|
||||||
|
export function setValue(newValue) {
|
||||||
|
value = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const url = import.meta.url;
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function hello() {
|
||||||
|
return "hello, world!";
|
||||||
|
}
|
4
tests/specs/compile/npmrc/.npmrc
Normal file
4
tests/specs/compile/npmrc/.npmrc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
@denotest:registry=http://127.0.0.1:4261/
|
||||||
|
//127.0.0.1:4261/denotest/:_authToken=private-reg-token
|
||||||
|
@denotest2:registry=http://127.0.0.1:4262/
|
||||||
|
//127.0.0.1:4262/denotest2/:_authToken=private-reg-token2
|
28
tests/specs/compile/npmrc/__test__.jsonc
Normal file
28
tests/specs/compile/npmrc/__test__.jsonc
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"envs": {
|
||||||
|
"DENO_FUTURE": "1"
|
||||||
|
},
|
||||||
|
"tempDir": true,
|
||||||
|
"steps": [{
|
||||||
|
"args": "install",
|
||||||
|
"output": "install.out"
|
||||||
|
}, {
|
||||||
|
"if": "unix",
|
||||||
|
"args": "compile --output main main.js",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
}, {
|
||||||
|
"if": "unix",
|
||||||
|
"commandName": "./main",
|
||||||
|
"args": [],
|
||||||
|
"output": "main.out"
|
||||||
|
}, {
|
||||||
|
"if": "windows",
|
||||||
|
"args": "compile --output main.exe main.js",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
}, {
|
||||||
|
"if": "windows",
|
||||||
|
"commandName": "./main.exe",
|
||||||
|
"args": [],
|
||||||
|
"output": "main.out"
|
||||||
|
}]
|
||||||
|
}
|
9
tests/specs/compile/npmrc/install.out
Normal file
9
tests/specs/compile/npmrc/install.out
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag.
|
||||||
|
[UNORDERED_START]
|
||||||
|
Download http://127.0.0.1:4261/@denotest/basic
|
||||||
|
Download http://127.0.0.1:4262/@denotest2/basic
|
||||||
|
Download http://localhost:4261/@denotest/basic/1.0.0.tgz
|
||||||
|
Download http://localhost:4262/@denotest2/basic/1.0.0.tgz
|
||||||
|
Initialize @denotest2/basic@1.0.0
|
||||||
|
Initialize @denotest/basic@1.0.0
|
||||||
|
[UNORDERED_END]
|
8
tests/specs/compile/npmrc/main.js
Normal file
8
tests/specs/compile/npmrc/main.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { getValue, setValue } from "@denotest/basic";
|
||||||
|
import * as test from "@denotest2/basic";
|
||||||
|
|
||||||
|
console.log(getValue());
|
||||||
|
setValue(42);
|
||||||
|
console.log(getValue());
|
||||||
|
|
||||||
|
console.log(test.getValue());
|
3
tests/specs/compile/npmrc/main.out
Normal file
3
tests/specs/compile/npmrc/main.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
0
|
||||||
|
42
|
||||||
|
0
|
8
tests/specs/compile/npmrc/package.json
Normal file
8
tests/specs/compile/npmrc/package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "npmrc_test",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"@denotest/basic": "1.0.0",
|
||||||
|
"@denotest2/basic": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
4
tests/specs/npm/npmrc/.npmrc
Normal file
4
tests/specs/npm/npmrc/.npmrc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
@denotest:registry=http://127.0.0.1:4261/
|
||||||
|
//127.0.0.1:4261/denotest/:_auth=ZGVubzpsYW5k
|
||||||
|
@denotest2:registry=http://127.0.0.1:4262/
|
||||||
|
//127.0.0.1:4262/denotest2/:_auth=ZGVubzpsYW5kMg==
|
13
tests/specs/npm/npmrc/__test__.jsonc
Normal file
13
tests/specs/npm/npmrc/__test__.jsonc
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"envs": {
|
||||||
|
"DENO_FUTURE": "1"
|
||||||
|
},
|
||||||
|
"tempDir": true,
|
||||||
|
"steps": [{
|
||||||
|
"args": "install",
|
||||||
|
"output": "install.out"
|
||||||
|
}, {
|
||||||
|
"args": "run -A main.js",
|
||||||
|
"output": "main.out"
|
||||||
|
}]
|
||||||
|
}
|
9
tests/specs/npm/npmrc/install.out
Normal file
9
tests/specs/npm/npmrc/install.out
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag.
|
||||||
|
[UNORDERED_START]
|
||||||
|
Download http://127.0.0.1:4261/@denotest/basic
|
||||||
|
Download http://127.0.0.1:4262/@denotest2/basic
|
||||||
|
Download http://localhost:4261/@denotest/basic/1.0.0.tgz
|
||||||
|
Download http://localhost:4262/@denotest2/basic/1.0.0.tgz
|
||||||
|
Initialize @denotest2/basic@1.0.0
|
||||||
|
Initialize @denotest/basic@1.0.0
|
||||||
|
[UNORDERED_END]
|
8
tests/specs/npm/npmrc/main.js
Normal file
8
tests/specs/npm/npmrc/main.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { getValue, setValue } from "@denotest/basic";
|
||||||
|
import * as test from "@denotest2/basic";
|
||||||
|
|
||||||
|
console.log(getValue());
|
||||||
|
setValue(42);
|
||||||
|
console.log(getValue());
|
||||||
|
|
||||||
|
console.log(test.getValue());
|
3
tests/specs/npm/npmrc/main.out
Normal file
3
tests/specs/npm/npmrc/main.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
0
|
||||||
|
42
|
||||||
|
0
|
8
tests/specs/npm/npmrc/package.json
Normal file
8
tests/specs/npm/npmrc/package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "npmrc_test",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"@denotest/basic": "1.0.0",
|
||||||
|
"@denotest2/basic": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
2
tests/specs/npm/npmrc_bad_token/.npmrc
Normal file
2
tests/specs/npm/npmrc_bad_token/.npmrc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@denotest:registry=http://127.0.0.1:4261/
|
||||||
|
//127.0.0.1:4261/denotest/:_authToken=invalid-token
|
9
tests/specs/npm/npmrc_bad_token/__test__.jsonc
Normal file
9
tests/specs/npm/npmrc_bad_token/__test__.jsonc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"envs": {
|
||||||
|
"DENO_FUTURE": "1"
|
||||||
|
},
|
||||||
|
"tempDir": true,
|
||||||
|
"args": "install",
|
||||||
|
"output": "main.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
5
tests/specs/npm/npmrc_bad_token/main.js
Normal file
5
tests/specs/npm/npmrc_bad_token/main.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { getValue, setValue } from "@denotest/basic";
|
||||||
|
|
||||||
|
console.log(getValue());
|
||||||
|
setValue(42);
|
||||||
|
console.log(getValue());
|
4
tests/specs/npm/npmrc_bad_token/main.out
Normal file
4
tests/specs/npm/npmrc_bad_token/main.out
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag.
|
||||||
|
Download http://127.0.0.1:4261/@denotest/basic
|
||||||
|
error: Error getting response at http://127.0.0.1:4261/@denotest/basic for package "@denotest/basic": Bad response: 401
|
||||||
|
[WILDCARD]
|
7
tests/specs/npm/npmrc_bad_token/package.json
Normal file
7
tests/specs/npm/npmrc_bad_token/package.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"name": "npmrc_test",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"@denotest/basic": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
4
tests/specs/npm/npmrc_basic_auth/.npmrc
Normal file
4
tests/specs/npm/npmrc_basic_auth/.npmrc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
@denotest:registry=http://127.0.0.1:4261/
|
||||||
|
//127.0.0.1:4261/denotest/:_authToken=private-reg-token
|
||||||
|
@denotest2:registry=http://127.0.0.1:4262/
|
||||||
|
//127.0.0.1:4262/denotest2/:_authToken=private-reg-token2
|
13
tests/specs/npm/npmrc_basic_auth/__test__.jsonc
Normal file
13
tests/specs/npm/npmrc_basic_auth/__test__.jsonc
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"envs": {
|
||||||
|
"DENO_FUTURE": "1"
|
||||||
|
},
|
||||||
|
"tempDir": true,
|
||||||
|
"steps": [{
|
||||||
|
"args": "install",
|
||||||
|
"output": "install.out"
|
||||||
|
}, {
|
||||||
|
"args": "run -A main.js",
|
||||||
|
"output": "main.out"
|
||||||
|
}]
|
||||||
|
}
|
9
tests/specs/npm/npmrc_basic_auth/install.out
Normal file
9
tests/specs/npm/npmrc_basic_auth/install.out
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag.
|
||||||
|
[UNORDERED_START]
|
||||||
|
Download http://127.0.0.1:4261/@denotest/basic
|
||||||
|
Download http://127.0.0.1:4262/@denotest2/basic
|
||||||
|
Download http://localhost:4261/@denotest/basic/1.0.0.tgz
|
||||||
|
Download http://localhost:4262/@denotest2/basic/1.0.0.tgz
|
||||||
|
Initialize @denotest2/basic@1.0.0
|
||||||
|
Initialize @denotest/basic@1.0.0
|
||||||
|
[UNORDERED_END]
|
8
tests/specs/npm/npmrc_basic_auth/main.js
Normal file
8
tests/specs/npm/npmrc_basic_auth/main.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { getValue, setValue } from "@denotest/basic";
|
||||||
|
import * as test from "@denotest2/basic";
|
||||||
|
|
||||||
|
console.log(getValue());
|
||||||
|
setValue(42);
|
||||||
|
console.log(getValue());
|
||||||
|
|
||||||
|
console.log(test.getValue());
|
3
tests/specs/npm/npmrc_basic_auth/main.out
Normal file
3
tests/specs/npm/npmrc_basic_auth/main.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
0
|
||||||
|
42
|
||||||
|
0
|
8
tests/specs/npm/npmrc_basic_auth/package.json
Normal file
8
tests/specs/npm/npmrc_basic_auth/package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "npmrc_test",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"@denotest/basic": "1.0.0",
|
||||||
|
"@denotest2/basic": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
2
tests/specs/npm/npmrc_deno_json/.npmrc
Normal file
2
tests/specs/npm/npmrc_deno_json/.npmrc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@denotest:registry=http://127.0.0.1:4261/
|
||||||
|
//127.0.0.1:4261/denotest/:_authToken=private-reg-token
|
8
tests/specs/npm/npmrc_deno_json/__test__.jsonc
Normal file
8
tests/specs/npm/npmrc_deno_json/__test__.jsonc
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"envs": {
|
||||||
|
"DENO_FUTURE": "1"
|
||||||
|
},
|
||||||
|
"tempDir": true,
|
||||||
|
"args": "run -A main.js",
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
3
tests/specs/npm/npmrc_deno_json/deno.json
Normal file
3
tests/specs/npm/npmrc_deno_json/deno.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"imports": {}
|
||||||
|
}
|
5
tests/specs/npm/npmrc_deno_json/main.js
Normal file
5
tests/specs/npm/npmrc_deno_json/main.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { getValue, setValue } from "npm:@denotest/basic";
|
||||||
|
|
||||||
|
console.log(getValue());
|
||||||
|
setValue(42);
|
||||||
|
console.log(getValue());
|
4
tests/specs/npm/npmrc_deno_json/main.out
Normal file
4
tests/specs/npm/npmrc_deno_json/main.out
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Download http://127.0.0.1:4261/@denotest/basic
|
||||||
|
Download http://localhost:4261/@denotest/basic/1.0.0.tgz
|
||||||
|
0
|
||||||
|
42
|
2
tests/specs/npm/npmrc_not_next_to_package_json/.npmrc
Normal file
2
tests/specs/npm/npmrc_not_next_to_package_json/.npmrc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@denotest:registry=http://127.0.0.1:4261/
|
||||||
|
//127.0.0.1:4261/denotest/:_authToken=private-reg-token
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"envs": {
|
||||||
|
"DENO_FUTURE": "1"
|
||||||
|
},
|
||||||
|
"tempDir": true,
|
||||||
|
"args": "install -A -L debug",
|
||||||
|
"output": "main.out",
|
||||||
|
"cwd": "subdir"
|
||||||
|
}
|
6
tests/specs/npm/npmrc_not_next_to_package_json/main.out
Normal file
6
tests/specs/npm/npmrc_not_next_to_package_json/main.out
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[# This test is still downloading code, because we have a private registry]
|
||||||
|
[# that serves the same packages. The important bit is the message below.]
|
||||||
|
[WILDCARD] No .npmrc file found
|
||||||
|
[WILDCARD]
|
||||||
|
Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz
|
||||||
|
Initialize @denotest/esm-basic@1.0.0
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { getValue, setValue } from "@denotest/esm-basic";
|
||||||
|
|
||||||
|
console.log(getValue());
|
||||||
|
setValue(42);
|
||||||
|
console.log(getValue());
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"name": "npmrc_test",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"@denotest/esm-basic": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -307,7 +307,7 @@ async fn get_tcp_listener_stream(
|
||||||
futures::stream::select_all(listeners)
|
futures::stream::select_all(listeners)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const TEST_SERVERS_COUNT: usize = 28;
|
pub const TEST_SERVERS_COUNT: usize = 30;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct HttpServerCount {
|
struct HttpServerCount {
|
||||||
|
|
|
@ -30,7 +30,6 @@ pub static PUBLIC_TEST_NPM_REGISTRY: Lazy<TestNpmRegistry> = Lazy::new(|| {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: rewrite to use config
|
|
||||||
pub static PRIVATE_TEST_NPM_REGISTRY_1: Lazy<TestNpmRegistry> =
|
pub static PRIVATE_TEST_NPM_REGISTRY_1: Lazy<TestNpmRegistry> =
|
||||||
Lazy::new(|| {
|
Lazy::new(|| {
|
||||||
TestNpmRegistry::new(
|
TestNpmRegistry::new(
|
||||||
|
@ -43,6 +42,18 @@ pub static PRIVATE_TEST_NPM_REGISTRY_1: Lazy<TestNpmRegistry> =
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pub static PRIVATE_TEST_NPM_REGISTRY_2: Lazy<TestNpmRegistry> =
|
||||||
|
Lazy::new(|| {
|
||||||
|
TestNpmRegistry::new(
|
||||||
|
NpmRegistryKind::Private,
|
||||||
|
&format!(
|
||||||
|
"http://localhost:{}",
|
||||||
|
crate::servers::PRIVATE_NPM_REGISTRY_2_PORT
|
||||||
|
),
|
||||||
|
"npm-private2",
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
pub enum NpmRegistryKind {
|
pub enum NpmRegistryKind {
|
||||||
Public,
|
Public,
|
||||||
Private,
|
Private,
|
||||||
|
|
|
@ -90,6 +90,7 @@ const JSR_REGISTRY_SERVER_PORT: u16 = 4250;
|
||||||
const PROVENANCE_MOCK_SERVER_PORT: u16 = 4251;
|
const PROVENANCE_MOCK_SERVER_PORT: u16 = 4251;
|
||||||
pub(crate) const PUBLIC_NPM_REGISTRY_PORT: u16 = 4260;
|
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_1_PORT: u16 = 4261;
|
||||||
|
pub(crate) const PRIVATE_NPM_REGISTRY_2_PORT: u16 = 4262;
|
||||||
|
|
||||||
// Use the single-threaded scheduler. The hyper server is used as a point of
|
// 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
|
// comparison for the (single-threaded!) benchmarks in cli/bench. We're not
|
||||||
|
@ -140,6 +141,8 @@ pub async fn run_all_servers() {
|
||||||
npm_registry::public_npm_registry(PUBLIC_NPM_REGISTRY_PORT);
|
npm_registry::public_npm_registry(PUBLIC_NPM_REGISTRY_PORT);
|
||||||
let private_npm_registry_1_server_futs =
|
let private_npm_registry_1_server_futs =
|
||||||
npm_registry::private_npm_registry1(PRIVATE_NPM_REGISTRY_1_PORT);
|
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 mut futures = vec![
|
let mut futures = vec![
|
||||||
redirect_server_fut.boxed_local(),
|
redirect_server_fut.boxed_local(),
|
||||||
|
@ -169,6 +172,7 @@ pub async fn run_all_servers() {
|
||||||
];
|
];
|
||||||
futures.extend(npm_registry_server_futs);
|
futures.extend(npm_registry_server_futs);
|
||||||
futures.extend(private_npm_registry_1_server_futs);
|
futures.extend(private_npm_registry_1_server_futs);
|
||||||
|
futures.extend(private_npm_registry_2_server_futs);
|
||||||
|
|
||||||
assert_eq!(futures.len(), TEST_SERVERS_COUNT);
|
assert_eq!(futures.len(), TEST_SERVERS_COUNT);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,12 @@ pub fn public_npm_registry(port: u16) -> Vec<LocalBoxFuture<'static, ()>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRIVATE_NPM_REGISTRY_AUTH_TOKEN: &str = "private-reg-token";
|
const PRIVATE_NPM_REGISTRY_AUTH_TOKEN: &str = "private-reg-token";
|
||||||
|
const PRIVATE_NPM_REGISTRY_2_AUTH_TOKEN: &str = "private-reg-token2";
|
||||||
|
|
||||||
|
// `deno:land` encoded using base64
|
||||||
|
const PRIVATE_NPM_REGISTRY_AUTH_BASE64: &str = "ZGVubzpsYW5k";
|
||||||
|
// `deno:land2` encoded using base64
|
||||||
|
const PRIVATE_NPM_REGISTRY_2_AUTH_BASE64: &str = "ZGVubzpsYW5kMg==";
|
||||||
|
|
||||||
pub fn private_npm_registry1(port: u16) -> Vec<LocalBoxFuture<'static, ()>> {
|
pub fn private_npm_registry1(port: u16) -> Vec<LocalBoxFuture<'static, ()>> {
|
||||||
run_npm_server(
|
run_npm_server(
|
||||||
|
@ -42,6 +48,14 @@ pub fn private_npm_registry1(port: u16) -> Vec<LocalBoxFuture<'static, ()>> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn private_npm_registry2(port: u16) -> Vec<LocalBoxFuture<'static, ()>> {
|
||||||
|
run_npm_server(
|
||||||
|
port,
|
||||||
|
"npm private registry server error",
|
||||||
|
private_npm_registry2_handler,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn run_npm_server<F, S>(
|
fn run_npm_server<F, S>(
|
||||||
port: u16,
|
port: u16,
|
||||||
error_msg: &'static str,
|
error_msg: &'static str,
|
||||||
|
@ -91,7 +105,9 @@ async fn private_npm_registry1_handler(
|
||||||
.get("authorization")
|
.get("authorization")
|
||||||
.and_then(|x| x.to_str().ok())
|
.and_then(|x| x.to_str().ok())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
if auth != format!("Bearer {}", PRIVATE_NPM_REGISTRY_AUTH_TOKEN) {
|
if auth != format!("Bearer {}", PRIVATE_NPM_REGISTRY_AUTH_TOKEN)
|
||||||
|
&& auth != format!("Basic {}", PRIVATE_NPM_REGISTRY_AUTH_BASE64)
|
||||||
|
{
|
||||||
return Ok(
|
return Ok(
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.status(StatusCode::UNAUTHORIZED)
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
@ -103,6 +119,28 @@ async fn private_npm_registry1_handler(
|
||||||
handle_req_for_registry(req, &npm::PRIVATE_TEST_NPM_REGISTRY_1).await
|
handle_req_for_registry(req, &npm::PRIVATE_TEST_NPM_REGISTRY_1).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn private_npm_registry2_handler(
|
||||||
|
req: Request<hyper::body::Incoming>,
|
||||||
|
) -> Result<Response<UnsyncBoxBody<Bytes, Infallible>>, anyhow::Error> {
|
||||||
|
let auth = req
|
||||||
|
.headers()
|
||||||
|
.get("authorization")
|
||||||
|
.and_then(|x| x.to_str().ok())
|
||||||
|
.unwrap_or_default();
|
||||||
|
if auth != format!("Bearer {}", PRIVATE_NPM_REGISTRY_2_AUTH_TOKEN)
|
||||||
|
&& auth != format!("Basic {}", PRIVATE_NPM_REGISTRY_2_AUTH_BASE64)
|
||||||
|
{
|
||||||
|
return Ok(
|
||||||
|
Response::builder()
|
||||||
|
.status(StatusCode::UNAUTHORIZED)
|
||||||
|
.body(empty_body())
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_req_for_registry(req, &npm::PRIVATE_TEST_NPM_REGISTRY_2).await
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_req_for_registry(
|
async fn handle_req_for_registry(
|
||||||
req: Request<Incoming>,
|
req: Request<Incoming>,
|
||||||
test_npm_registry: &npm::TestNpmRegistry,
|
test_npm_registry: &npm::TestNpmRegistry,
|
||||||
|
|
Loading…
Reference in a new issue