summaryrefslogtreecommitdiff
path: root/cli/args/mod.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-01-25 21:13:40 +0100
committerGitHub <noreply@github.com>2023-01-25 21:13:40 +0100
commitc6c8c91a6e4b7a2b6eed02d3e2f5db25c124d9a0 (patch)
tree1fe8e9ab2175154d44e78d153dd760e56dc1c860 /cli/args/mod.rs
parentb5b4887c4a5fefdeb5592ebaadcc941281d0c4d5 (diff)
feat: embed import map in the config file (#17478)
This commit changes handling of config file to enable specifying "imports" and "scopes" objects effectively making the configuration file an import map. "imports" and "scopes" take precedence over "importMap" configuration, but have lower priority than "--importmap" CLI flag. Co-authored-by: David Sherret <dsherret@users.noreply.github.com> Co-authored-by: David Sherret <dsherret@gmail.com>
Diffstat (limited to 'cli/args/mod.rs')
-rw-r--r--cli/args/mod.rs80
1 files changed, 75 insertions, 5 deletions
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index 4cb960238..1bf294018 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -2,10 +2,12 @@
mod config_file;
mod flags;
-mod lockfile;
-
mod flags_allow_net;
+mod import_map;
+mod lockfile;
+pub use self::import_map::import_map_from_value;
+use ::import_map::ImportMap;
pub use config_file::BenchConfig;
pub use config_file::CompilerOptions;
pub use config_file::ConfigFile;
@@ -19,6 +21,8 @@ pub use config_file::TsConfig;
pub use config_file::TsConfigForEmit;
pub use config_file::TsConfigType;
pub use config_file::TsTypeLib;
+use deno_core::serde_json;
+use deno_runtime::permissions::PermissionsContainer;
pub use flags::*;
pub use lockfile::Lockfile;
pub use lockfile::LockfileError;
@@ -49,6 +53,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use crate::cache::DenoDir;
+use crate::file_fetcher::FileFetcher;
use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::version;
@@ -547,12 +552,13 @@ impl CliOptions {
}
/// Based on an optional command line import map path and an optional
- /// configuration file, return a resolved module specifier to an import map.
+ /// configuration file, return a resolved module specifier to an import map
+ /// and a boolean indicating if unknown keys should not result in diagnostics.
pub fn resolve_import_map_specifier(
&self,
) -> Result<Option<ModuleSpecifier>, AnyError> {
match self.overrides.import_map_specifier.clone() {
- Some(path) => Ok(path),
+ Some(maybe_path) => Ok(maybe_path),
None => resolve_import_map_specifier(
self.flags.import_map_path.as_deref(),
self.maybe_config_file.as_ref(),
@@ -560,6 +566,45 @@ impl CliOptions {
}
}
+ pub async fn resolve_import_map(
+ &self,
+ file_fetcher: &FileFetcher,
+ ) -> Result<Option<ImportMap>, AnyError> {
+ let import_map_specifier = match self.resolve_import_map_specifier()? {
+ Some(specifier) => specifier,
+ None => return Ok(None),
+ };
+ self
+ .resolve_import_map_from_specifier(&import_map_specifier, file_fetcher)
+ .await
+ .context(format!(
+ "Unable to load '{}' import map",
+ import_map_specifier
+ ))
+ .map(Some)
+ }
+
+ async fn resolve_import_map_from_specifier(
+ &self,
+ import_map_specifier: &ModuleSpecifier,
+ file_fetcher: &FileFetcher,
+ ) -> Result<ImportMap, AnyError> {
+ let import_map_config = self
+ .get_maybe_config_file()
+ .as_ref()
+ .filter(|c| c.specifier == *import_map_specifier);
+ let value: serde_json::Value = match import_map_config {
+ Some(config) => config.to_import_map_value(),
+ None => {
+ let file = file_fetcher
+ .fetch(import_map_specifier, PermissionsContainer::allow_all())
+ .await?;
+ serde_json::from_str(&file.source)?
+ }
+ };
+ import_map_from_value(import_map_specifier, value)
+ }
+
/// Overrides the import map specifier to use.
pub fn set_import_map_specifier(&mut self, path: Option<ModuleSpecifier>) {
self.overrides.import_map_specifier = Some(path);
@@ -907,6 +952,16 @@ fn resolve_import_map_specifier(
.context(format!("Bad URL (\"{}\") for import map.", import_map_path))?;
return Ok(Some(specifier));
} else if let Some(config_file) = &maybe_config_file {
+ // if the config file is an import map we prefer to use it, over `importMap`
+ // field
+ if config_file.is_an_import_map() {
+ if let Some(_import_map_path) = config_file.to_import_map_path() {
+ log::warn!("{} \"importMap\" setting is ignored when \"imports\" or \"scopes\" are specified in the config file.", colors::yellow("Warning"));
+ }
+
+ return Ok(Some(config_file.specifier.clone()));
+ }
+
// when the import map is specifier in a config file, it needs to be
// resolved relative to the config file, versus the CWD like with the flag
// and with config files, we support both local and remote config files,
@@ -990,7 +1045,7 @@ mod test {
let actual = actual.unwrap();
assert_eq!(
actual,
- Some(ModuleSpecifier::parse("file:///deno/import_map.json").unwrap())
+ Some(ModuleSpecifier::parse("file:///deno/import_map.json").unwrap(),)
);
}
@@ -1052,6 +1107,21 @@ mod test {
}
#[test]
+ fn resolve_import_map_embedded_take_precedence() {
+ let config_text = r#"{
+ "importMap": "import_map.json",
+ "imports": {},
+ }"#;
+ let config_specifier =
+ ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
+ let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
+ let actual = resolve_import_map_specifier(None, Some(&config_file));
+ assert!(actual.is_ok());
+ let actual = actual.unwrap();
+ assert_eq!(actual, Some(config_specifier));
+ }
+
+ #[test]
fn resolve_import_map_none() {
let config_text = r#"{}"#;
let config_specifier =