Skip to content

feat(config_file): add config file option npmRegistry #19317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion cli/args/config_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use deno_core::serde::Serializer;
use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use indexmap::IndexMap;
use std::borrow::Cow;
Expand Down Expand Up @@ -664,6 +665,7 @@ pub struct ConfigFileJson {
pub lock: Option<Value>,
pub exclude: Option<Value>,
pub node_modules_dir: Option<bool>,
pub npm_registry: Option<String>,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -859,6 +861,24 @@ impl ConfigFile {
self.json.node_modules_dir
}

pub fn to_npm_registry(&self) -> Option<Url> {
self.json.npm_registry.as_ref().and_then(|registry_url| {
let registry_url = format!("{}/", registry_url.trim_end_matches('/'));
match Url::parse(&registry_url) {
Ok(url) => {
return Some(url);
}
Err(err) => {
log::debug!(
"Invalid \"npmRegistry\" configuration option: {:#}",
err,
);
}
}
None
})
}

pub fn to_import_map_value(&self) -> Value {
let mut value = serde_json::Map::with_capacity(2);
if let Some(imports) = &self.json.imports {
Expand Down Expand Up @@ -1329,7 +1349,8 @@ mod tests {
"tasks": {
"build": "deno run --allow-read --allow-write build.ts",
"server": "deno run --allow-net --allow-read server.ts"
}
},
"npmRegistry": "https://deno.land"
}"#;
let config_dir = ModuleSpecifier::parse("file:///deno/").unwrap();
let config_specifier = config_dir.join("tsconfig.json").unwrap();
Expand Down Expand Up @@ -1390,6 +1411,11 @@ mod tests {
tasks_config["server"],
"deno run --allow-net --allow-read server.ts"
);

assert_eq!(
config_file.to_npm_registry().unwrap(),
Url::parse("https://deno.land/").unwrap()
);
}

/// if either "include" or "exclude" is specified, "files" is ignored
Expand Down
7 changes: 7 additions & 0 deletions cli/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,13 @@ impl CliOptions {
&self.initial_cwd
}

pub fn maybe_npm_registry(&self) -> Option<Url> {
self
.maybe_config_file
.as_ref()
.and_then(|f| f.to_npm_registry())
}

pub fn maybe_config_file_specifier(&self) -> Option<ModuleSpecifier> {
self.maybe_config_file.as_ref().map(|f| f.specifier.clone())
}
Expand Down
18 changes: 15 additions & 3 deletions cli/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use crate::worker::HasNodeSpecifierChecker;

use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use deno_core::url::Url;

use deno_runtime::deno_fs;
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
Expand Down Expand Up @@ -266,6 +267,17 @@ impl CliFactory {
.get_or_init(|| self.options.maybe_lockfile())
}

fn npm_registry(&self) -> Url {
if let Some(url) = CliNpmRegistryApi::npm_registry_override() {
url.to_owned()
} else {
self
.options
.maybe_npm_registry()
.unwrap_or_else(|| CliNpmRegistryApi::default_npm_registry().to_owned())
}
}

pub fn npm_cache(&self) -> Result<&Arc<NpmCache>, AnyError> {
self.services.npm_cache.get_or_try_init(|| {
Ok(Arc::new(NpmCache::new(
Expand All @@ -280,7 +292,7 @@ impl CliFactory {
pub fn npm_api(&self) -> Result<&Arc<CliNpmRegistryApi>, AnyError> {
self.services.npm_api.get_or_try_init(|| {
Ok(Arc::new(CliNpmRegistryApi::new(
CliNpmRegistryApi::default_url().to_owned(),
self.npm_registry(),
self.npm_cache()?.clone(),
self.http_client().clone(),
self.text_only_progress_bar().clone(),
Expand Down Expand Up @@ -317,7 +329,7 @@ impl CliFactory {
fs.clone(),
self.npm_cache()?.clone(),
self.text_only_progress_bar(),
CliNpmRegistryApi::default_url().to_owned(),
self.npm_registry(),
npm_resolution.clone(),
self.options.node_modules_dir_path(),
self.options.npm_system_info(),
Expand All @@ -340,7 +352,7 @@ impl CliFactory {
self.fs().clone(),
self.npm_cache()?.clone(),
self.text_only_progress_bar(),
CliNpmRegistryApi::default_url().to_owned(),
self.npm_registry(),
self.npm_resolution().await?.clone(),
// when an explicit path is provided here, it will create the
// local node_modules variant of an npm fs resolver
Expand Down
18 changes: 15 additions & 3 deletions cli/lsp/language_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,12 +966,13 @@ impl Inner {
return; // no need to do anything
}

let registry_url = CliNpmRegistryApi::default_url();
let registry_url = self.npm_registry();

let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
(self.npm.api, self.npm.cache) = create_npm_api_and_cache(
&deno_dir,
self.http_client.clone(),
registry_url,
&registry_url,
&progress_bar,
);
let maybe_snapshot = match self.maybe_lockfile() {
Expand All @@ -988,7 +989,7 @@ impl Inner {
};
(self.npm.resolver, self.npm.resolution) =
create_npm_resolver_and_resolution(
registry_url,
&registry_url,
progress_bar,
self.npm.api.clone(),
self.npm.cache.clone(),
Expand Down Expand Up @@ -1218,6 +1219,17 @@ impl Inner {
self.maybe_config_file_info.as_ref().map(|c| &c.config_file)
}

fn npm_registry(&self) -> Url {
if let Some(url) = CliNpmRegistryApi::npm_registry_override() {
url.to_owned()
} else {
self
.maybe_config_file()
.and_then(|f| f.to_npm_registry())
.unwrap_or_else(|| CliNpmRegistryApi::default_npm_registry().clone())
}
}

fn maybe_lockfile(&self) -> Option<&Arc<Mutex<Lockfile>>> {
self
.maybe_config_file_info
Expand Down
22 changes: 17 additions & 5 deletions cli/npm/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,43 @@ use crate::util::sync::AtomicFlag;
use super::cache::should_sync_download;
use super::cache::NpmCache;

static NPM_REGISTRY_DEFAULT_URL: Lazy<Url> = Lazy::new(|| {
static NPM_REGISTRY_OVERRIDE: Lazy<Option<Url>> = Lazy::new(|| {
let env_var_name = "NPM_CONFIG_REGISTRY";
if let Ok(registry_url) = std::env::var(env_var_name) {
// ensure there is a trailing slash for the directory
let registry_url = format!("{}/", registry_url.trim_end_matches('/'));
match Url::parse(&registry_url) {
Ok(url) => {
return url;
return Some(url);
}
Err(err) => {
log::debug!("Invalid {} environment variable: {:#}", env_var_name, err,);
}
}
}

Url::parse("https://registry.npmjs.org").unwrap()
None
});

static NPM_REGISTRY_DEFAULT_URL: Lazy<Url> =
Lazy::new(|| Url::parse("https://registry.npmjs.org").unwrap());

#[derive(Debug)]
pub struct CliNpmRegistryApi(Option<Arc<CliNpmRegistryApiInner>>);

impl CliNpmRegistryApi {
pub fn default_url() -> &'static Url {
pub fn npm_registry_override() -> &'static Option<Url> {
&NPM_REGISTRY_OVERRIDE
}
pub fn default_npm_registry() -> &'static Url {
&NPM_REGISTRY_DEFAULT_URL
}
pub fn default_url() -> &'static Url {
if let Some(url) = Self::npm_registry_override() {
url
} else {
Self::default_npm_registry()
}
}

pub fn new(
base_url: Url,
Expand Down
4 changes: 4 additions & 0 deletions cli/schemas/config-file.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@
"description": "Enables or disables the use of a local node_modules folder for npm packages. Alternatively, use the `--node-modules-dir` or `--node-modules-dir=false` flag. Requires Deno 1.34 or later.",
"type": "boolean"
},
"npmRegistry": {
"description": "The npm registry to use for npm specifiers.",
"type": "string"
},
"tasks": {
"description": "Configuration for deno task",
"type": "object",
Expand Down