summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorBartek Iwańczuk <biwanczuk@gmail.com>2024-01-24 23:44:06 +0100
committerGitHub <noreply@github.com>2024-01-24 23:44:06 +0100
commit44f8b05f5bf45453496e80c69dc7850aa98c9af8 (patch)
treeba31d15374e1b658a444e5727abc7b157a2efc73 /cli
parent801ed74118baabef49842bbfb2164f971d2cdb03 (diff)
feat: Expand 'imports' section of deno.json (#22087)
This commit adds automatic expansion of "imports" field in "deno.json" file. If "npm:" or "jsr:" imports are encountered we automatically try to add a "directory" remapping. Previously users had to specify entries for both `foo` and `foo/` to be able to import like `import { symbol1 } from "foo";` and `import { symbol2 } from "foo/some_file.js"`: ``` { "imports": { "foo": "npm:@foo/bar", "foo/": "npm:/@foo/bar/", } ``` With this change users can only add entry for `foo`: ``` { "imports": { "foo": "npm:@foo/bar", } ``` The entry for `foo/` will be provided automatically. Similarly if user provides "directory" remapping explicitly, we will not overwrite it.
Diffstat (limited to 'cli')
-rw-r--r--cli/args/mod.rs48
-rw-r--r--cli/tests/integration/run_tests.rs61
-rw-r--r--cli/tests/testdata/compile/npm_fs/main.ts2
-rw-r--r--cli/tests/testdata/npm/registry/@denotest/esm-basic/1.0.0/other.mjs3
-rw-r--r--cli/tests/testdata/package_json/basic/main.info.out2
5 files changed, 110 insertions, 6 deletions
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index 13ee9eeef..1e5d8754d 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -889,7 +889,19 @@ impl CliOptions {
.members
.iter()
.map(|member| {
- let import_map_value = member.config_file.to_import_map_value();
+ let mut import_map_value = member.config_file.to_import_map_value();
+
+ let expanded_import_map_value = ::import_map::ext::expand_imports(
+ ::import_map::ext::ImportMapConfig {
+ base_url: member.config_file.specifier.clone(),
+ import_map_value: import_map_value.clone(),
+ },
+ );
+
+ import_map_value
+ .as_object_mut()
+ .unwrap()
+ .insert("imports".to_string(), expanded_import_map_value);
::import_map::ext::ImportMapConfig {
base_url: member.config_file.specifier.clone(),
import_map_value,
@@ -906,12 +918,24 @@ impl CliOptions {
"Workspace config generated this import map {}",
serde_json::to_string_pretty(&import_map).unwrap()
);
- return import_map::import_map_from_value(
+ let maybe_import_map_result = import_map::import_map_from_value(
// TODO(bartlomieju): maybe should be stored on the workspace config?
&self.maybe_config_file.as_ref().unwrap().specifier,
import_map,
)
.map(Some);
+
+ return match maybe_import_map_result {
+ Ok(maybe_import_map) => {
+ if let Some(mut import_map) = maybe_import_map {
+ import_map.ext_expand_imports();
+ Ok(Some(import_map))
+ } else {
+ Ok(None)
+ }
+ }
+ Err(err) => Err(err),
+ };
}
}
@@ -919,7 +943,8 @@ impl CliOptions {
Some(specifier) => specifier,
None => return Ok(None),
};
- resolve_import_map_from_specifier(
+
+ let maybe_import_map_result = resolve_import_map_from_specifier(
&import_map_specifier,
self.maybe_config_file().as_ref(),
file_fetcher,
@@ -928,7 +953,22 @@ impl CliOptions {
.with_context(|| {
format!("Unable to load '{import_map_specifier}' import map")
})
- .map(Some)
+ .map(Some);
+
+ match maybe_import_map_result {
+ Ok(maybe_import_map) => {
+ if let Some(mut import_map) = maybe_import_map {
+ let url = import_map.base_url().as_str();
+ if url.ends_with("deno.json") || url.ends_with("deno.jsonc") {
+ import_map.ext_expand_imports();
+ }
+ Ok(Some(import_map))
+ } else {
+ Ok(None)
+ }
+ }
+ Err(err) => Err(err),
+ }
}
pub fn node_ipc_fd(&self) -> Option<i64> {
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index 6c82cfeec..b8acce94d 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -5113,3 +5113,64 @@ itest!(warn_on_deprecated_api_with_env_var {
http_server: true,
exit_code: 0,
});
+
+#[test]
+fn deno_json_imports_expand() {
+ let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
+ let dir = test_context.temp_dir();
+ dir.write(
+ "deno.json",
+ r#"{
+ "imports": {
+ "basic": "npm:@denotest/esm-basic"
+ }
+}"#,
+ );
+
+ dir.write(
+ "main.ts",
+ r#"
+// import map should resolve
+import { setValue, getValue } from "basic";
+// this entry should have been added automatically
+import { hello } from "basic/other.mjs";
+
+setValue(5);
+console.log(getValue());
+console.log(hello());
+"#,
+ );
+ let output = test_context.new_command().args("run main.ts").run();
+ output.assert_matches_text("[WILDCARD]5\nhello, world!\n");
+}
+
+#[test]
+fn deno_json_imports_expand_doesnt_overwrite_existing_entries() {
+ let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
+ let dir = test_context.temp_dir();
+ dir.write(
+ "deno.json",
+ r#"{
+ "imports": {
+ "basic": "npm:@denotest/esm-basic",
+ "basic/": "npm:/@denotest/sub-folders/folder_index_js/"
+ }
+}"#,
+ );
+
+ dir.write(
+ "main.ts",
+ r#"
+// import map should resolve
+import { setValue, getValue } from "basic";
+// this entry should map to explicitly specified "basic/" mapping
+import { add } from "basic/index.js";
+
+setValue(5);
+console.log(getValue());
+console.log(add(3, 4));
+"#,
+ );
+ let output = test_context.new_command().args("run main.ts").run();
+ output.assert_matches_text("[WILDCARD]5\n7\n");
+}
diff --git a/cli/tests/testdata/compile/npm_fs/main.ts b/cli/tests/testdata/compile/npm_fs/main.ts
index f9951d7a4..6361610a9 100644
--- a/cli/tests/testdata/compile/npm_fs/main.ts
+++ b/cli/tests/testdata/compile/npm_fs/main.ts
@@ -154,7 +154,7 @@ await assert.rejects(
}
// read dir
-const readDirNames = ["main.d.mts", "main.mjs", "package.json"];
+const readDirNames = ["main.d.mts", "main.mjs", "other.mjs", "package.json"];
{
const names = Array.from(Deno.readDirSync(dirPath))
.map((e) => e.name);
diff --git a/cli/tests/testdata/npm/registry/@denotest/esm-basic/1.0.0/other.mjs b/cli/tests/testdata/npm/registry/@denotest/esm-basic/1.0.0/other.mjs
new file mode 100644
index 000000000..00ed99da4
--- /dev/null
+++ b/cli/tests/testdata/npm/registry/@denotest/esm-basic/1.0.0/other.mjs
@@ -0,0 +1,3 @@
+export function hello() {
+ return "hello, world!";
+} \ No newline at end of file
diff --git a/cli/tests/testdata/package_json/basic/main.info.out b/cli/tests/testdata/package_json/basic/main.info.out
index b283a0ee0..892c0612a 100644
--- a/cli/tests/testdata/package_json/basic/main.info.out
+++ b/cli/tests/testdata/package_json/basic/main.info.out
@@ -5,4 +5,4 @@ size: [WILDCARD]
file:///[WILDCARD]/main.ts (63B)
└─┬ file:///[WILDCARD]/lib.ts (166B)
- └── npm:/@denotest/esm-basic@1.0.0 (416B)
+ └── npm:/@denotest/esm-basic@1.0.0 (471B)