fix(node): improve directory import error suggestion (#30619)
Some checks are pending
ci / test release macos-x86_64 (push) Blocked by required conditions
ci / test debug windows-x86_64 (push) Blocked by required conditions
ci / test release windows-x86_64 (push) Blocked by required conditions
ci / build libs (push) Blocked by required conditions
ci / pre-build (push) Waiting to run
ci / test debug linux-aarch64 (push) Blocked by required conditions
ci / test release linux-aarch64 (push) Blocked by required conditions
ci / test debug macos-aarch64 (push) Blocked by required conditions
ci / test release macos-aarch64 (push) Blocked by required conditions
ci / bench release linux-x86_64 (push) Blocked by required conditions
ci / lint debug linux-x86_64 (push) Blocked by required conditions
ci / lint debug macos-x86_64 (push) Blocked by required conditions
ci / lint debug windows-x86_64 (push) Blocked by required conditions
ci / test debug linux-x86_64 (push) Blocked by required conditions
ci / test release linux-x86_64 (push) Blocked by required conditions
ci / test debug macos-x86_64 (push) Blocked by required conditions
ci / publish canary (push) Blocked by required conditions

This commit is contained in:
David Sherret 2025-09-04 21:48:19 -04:00 committed by GitHub
parent eea93eb08a
commit db263a14d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 81 additions and 7 deletions

View file

@ -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<UrlOrPath>,
pub suggested_file_name: Option<&'static str>,
pub suggestion: Option<String>,
}
impl NodeJsErrorCoded for UnsupportedDirImportError {

View file

@ -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<String> {
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,

View file

@ -0,0 +1,5 @@
{
"args": "run main.ts",
"exitCode": 1,
"output": "error.out"
}

View file

@ -0,0 +1,3 @@
error: [ERR_UNSUPPORTED_DIR_IMPORT] Directory import [WILDLINE]
Did you mean to import 'package/dir.js'?
at [WILDLINE]

View file

@ -0,0 +1 @@
import {} from "package/dir";

View file

@ -0,0 +1,3 @@
{
"name": "package"
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -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'?

View file

@ -0,0 +1,5 @@
{
"args": "run main.ts",
"exitCode": 1,
"output": "error.out"
}

View file

@ -0,0 +1,3 @@
error: [ERR_UNSUPPORTED_DIR_IMPORT] Directory import [WILDLINE]
Did you mean to import 'fp-ts/lib/function.js'?
at [WILDLINE]

View file

@ -0,0 +1 @@
import {} from "fp-ts/function";

View file

@ -0,0 +1,3 @@
{
"main": "../lib/function.js"
}

View file

@ -0,0 +1,3 @@
{
"name": "fp-ts"
}

View file

@ -0,0 +1,2 @@
{
}