diff --git a/libs/node_resolver/errors.rs b/libs/node_resolver/errors.rs index a6f6413d93..bbe7c1af2b 100644 --- a/libs/node_resolver/errors.rs +++ b/libs/node_resolver/errors.rs @@ -892,13 +892,13 @@ impl NodeJsErrorCoded for ModuleNotFoundError { self.code(), dir_url, maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(), - suggested_file_name.map(|file_name| format!("\nDid you mean to import {file_name} within the directory?")).unwrap_or_default(), + suggestion.as_ref().map(|suggestion| format!("\nDid you mean to import '{suggestion}'?")).unwrap_or_default(), )] #[property("code" = self.code())] pub struct UnsupportedDirImportError { pub dir_url: UrlOrPath, pub maybe_referrer: Option, - pub suggested_file_name: Option<&'static str>, + pub suggestion: Option, } impl NodeJsErrorCoded for UnsupportedDirImportError { diff --git a/libs/node_resolver/resolution.rs b/libs/node_resolver/resolution.rs index b0b10e32ce..d77e34cbe7 100644 --- a/libs/node_resolver/resolution.rs +++ b/libs/node_resolver/resolution.rs @@ -564,14 +564,12 @@ impl< if resolution_mode == ResolutionMode::Import && !self.resolution_config.bundle_mode { - let suggested_file_name = ["index.mjs", "index.js", "index.cjs"] - .into_iter() - .find(|e| self.sys.is_file(&path.join(e))); + let suggestion = self.directory_import_suggestion(&path); Err( UnsupportedDirImportError { dir_url: UrlOrPath::Path(path.into_owned()), maybe_referrer: maybe_referrer.map(|r| r.display()), - suggested_file_name, + suggestion, } .into(), ) @@ -662,6 +660,51 @@ impl< } } + fn directory_import_suggestion( + &self, + dir_import_path: &Path, + ) -> Option { + let dir_index_paths = ["index.mjs", "index.js", "index.cjs"] + .into_iter() + .map(|file_name| dir_import_path.join(file_name)); + let file_paths = [ + with_known_extension(dir_import_path, "js"), + with_known_extension(dir_import_path, "mjs"), + with_known_extension(dir_import_path, "cjs"), + ]; + dir_index_paths + .chain(file_paths) + .chain( + std::iter::once_with(|| { + // check if this directory has a package.json + let package_json_path = dir_import_path.join("package.json"); + let pkg_json = self + .pkg_json_resolver + .load_package_json(&package_json_path) + .ok()??; + let main = pkg_json.main.as_ref()?; + Some(dir_import_path.join(main)) + }) + .flatten(), + ) + .map(|p| deno_path_util::normalize_path(Cow::Owned(p))) + .find(|p| self.sys.is_file(p)) + .and_then(|suggested_file_path| { + let pkg_json = self + .pkg_json_resolver + .get_closest_package_jsons(&suggested_file_path) + .filter_map(|pkg_json| pkg_json.ok()) + .find(|p| p.name.is_some())?; + let pkg_name = pkg_json.name.as_ref()?; + let sub_path = suggested_file_path + .strip_prefix(pkg_json.dir_path()) + .ok()? + .to_string_lossy() + .replace("\\", "/"); + Some(format!("{}/{}", pkg_name, sub_path)) + }) + } + pub fn resolve_package_subpath_from_deno_module( &self, package_dir: &Path, diff --git a/tests/specs/node/esm_dir_import/dir_same_name_file/__test__.jsonc b/tests/specs/node/esm_dir_import/dir_same_name_file/__test__.jsonc new file mode 100644 index 0000000000..c3dd85fb26 --- /dev/null +++ b/tests/specs/node/esm_dir_import/dir_same_name_file/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run main.ts", + "exitCode": 1, + "output": "error.out" +} diff --git a/tests/specs/node/esm_dir_import/dir_same_name_file/error.out b/tests/specs/node/esm_dir_import/dir_same_name_file/error.out new file mode 100644 index 0000000000..ebb6898ec5 --- /dev/null +++ b/tests/specs/node/esm_dir_import/dir_same_name_file/error.out @@ -0,0 +1,3 @@ +error: [ERR_UNSUPPORTED_DIR_IMPORT] Directory import [WILDLINE] +Did you mean to import 'package/dir.js'? + at [WILDLINE] diff --git a/tests/specs/node/esm_dir_import/dir_same_name_file/main.ts b/tests/specs/node/esm_dir_import/dir_same_name_file/main.ts new file mode 100644 index 0000000000..1010af7db3 --- /dev/null +++ b/tests/specs/node/esm_dir_import/dir_same_name_file/main.ts @@ -0,0 +1 @@ +import {} from "package/dir"; diff --git a/tests/specs/node/esm_dir_import/dir_same_name_file/node_modules/package/dir.js b/tests/specs/node/esm_dir_import/dir_same_name_file/node_modules/package/dir.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/node/esm_dir_import/dir_same_name_file/node_modules/package/dir/data.txt b/tests/specs/node/esm_dir_import/dir_same_name_file/node_modules/package/dir/data.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/node/esm_dir_import/dir_same_name_file/node_modules/package/package.json b/tests/specs/node/esm_dir_import/dir_same_name_file/node_modules/package/package.json new file mode 100644 index 0000000000..028ddbb95b --- /dev/null +++ b/tests/specs/node/esm_dir_import/dir_same_name_file/node_modules/package/package.json @@ -0,0 +1,3 @@ +{ + "name": "package" +} \ No newline at end of file diff --git a/tests/specs/node/esm_dir_import/dir_same_name_file/package.json b/tests/specs/node/esm_dir_import/dir_same_name_file/package.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/node/esm_dir_import/dir_same_name_file/package.json @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/specs/npm/directory_import/__test__.jsonc b/tests/specs/node/esm_dir_import/index_js/__test__.jsonc similarity index 100% rename from tests/specs/npm/directory_import/__test__.jsonc rename to tests/specs/node/esm_dir_import/index_js/__test__.jsonc diff --git a/tests/specs/npm/directory_import/folder_index_js.out b/tests/specs/node/esm_dir_import/index_js/folder_index_js.out similarity index 83% rename from tests/specs/npm/directory_import/folder_index_js.out rename to tests/specs/node/esm_dir_import/index_js/folder_index_js.out index 49f6e4b241..6f15803671 100644 --- a/tests/specs/npm/directory_import/folder_index_js.out +++ b/tests/specs/node/esm_dir_import/index_js/folder_index_js.out @@ -4,4 +4,4 @@ error: Could not resolve 'npm:@denotest/sub-folders@1.0.0/folder_index_js' Caused by: [ERR_UNSUPPORTED_DIR_IMPORT] Directory import 'file:///[WILDLINE]/folder_index_js' is not supported resolving ES modules imported from 'file:///[WILDLINE]/folder_index_js.ts' - Did you mean to import index.js within the directory? + Did you mean to import '@denotest/sub-folders/folder_index_js/index.js'? diff --git a/tests/specs/npm/directory_import/folder_index_js.ts b/tests/specs/node/esm_dir_import/index_js/folder_index_js.ts similarity index 100% rename from tests/specs/npm/directory_import/folder_index_js.ts rename to tests/specs/node/esm_dir_import/index_js/folder_index_js.ts diff --git a/tests/specs/npm/directory_import/folder_no_index.out b/tests/specs/node/esm_dir_import/index_js/folder_no_index.out similarity index 100% rename from tests/specs/npm/directory_import/folder_no_index.out rename to tests/specs/node/esm_dir_import/index_js/folder_no_index.out diff --git a/tests/specs/npm/directory_import/folder_no_index.ts b/tests/specs/node/esm_dir_import/index_js/folder_no_index.ts similarity index 100% rename from tests/specs/npm/directory_import/folder_no_index.ts rename to tests/specs/node/esm_dir_import/index_js/folder_no_index.ts diff --git a/tests/specs/node/esm_dir_import/package_json/__test__.jsonc b/tests/specs/node/esm_dir_import/package_json/__test__.jsonc new file mode 100644 index 0000000000..c3dd85fb26 --- /dev/null +++ b/tests/specs/node/esm_dir_import/package_json/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run main.ts", + "exitCode": 1, + "output": "error.out" +} diff --git a/tests/specs/node/esm_dir_import/package_json/error.out b/tests/specs/node/esm_dir_import/package_json/error.out new file mode 100644 index 0000000000..2b110c1282 --- /dev/null +++ b/tests/specs/node/esm_dir_import/package_json/error.out @@ -0,0 +1,3 @@ +error: [ERR_UNSUPPORTED_DIR_IMPORT] Directory import [WILDLINE] +Did you mean to import 'fp-ts/lib/function.js'? + at [WILDLINE] diff --git a/tests/specs/node/esm_dir_import/package_json/main.ts b/tests/specs/node/esm_dir_import/package_json/main.ts new file mode 100644 index 0000000000..d3472f17ef --- /dev/null +++ b/tests/specs/node/esm_dir_import/package_json/main.ts @@ -0,0 +1 @@ +import {} from "fp-ts/function"; diff --git a/tests/specs/node/esm_dir_import/package_json/node_modules/fp-ts/function/package.json b/tests/specs/node/esm_dir_import/package_json/node_modules/fp-ts/function/package.json new file mode 100644 index 0000000000..680ebf5991 --- /dev/null +++ b/tests/specs/node/esm_dir_import/package_json/node_modules/fp-ts/function/package.json @@ -0,0 +1,3 @@ +{ + "main": "../lib/function.js" +} \ No newline at end of file diff --git a/tests/specs/node/esm_dir_import/package_json/node_modules/fp-ts/lib/function.js b/tests/specs/node/esm_dir_import/package_json/node_modules/fp-ts/lib/function.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/specs/node/esm_dir_import/package_json/node_modules/fp-ts/package.json b/tests/specs/node/esm_dir_import/package_json/node_modules/fp-ts/package.json new file mode 100644 index 0000000000..ed1e5b18a9 --- /dev/null +++ b/tests/specs/node/esm_dir_import/package_json/node_modules/fp-ts/package.json @@ -0,0 +1,3 @@ +{ + "name": "fp-ts" +} \ No newline at end of file diff --git a/tests/specs/node/esm_dir_import/package_json/package.json b/tests/specs/node/esm_dir_import/package_json/package.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/tests/specs/node/esm_dir_import/package_json/package.json @@ -0,0 +1,2 @@ +{ +}