use std::path::Path;
use super::fallbacks::{nearest_package_manifest, try_workspace_package_fallback};
use super::path_info::extract_package_name;
use super::types::{ResolveContext, ResolveResult};
pub(super) fn aliased_specifier(
ctx: &ResolveContext<'_>,
from_file: &Path,
specifier: &str,
) -> Option<String> {
let alias = extract_package_name(specifier);
let target = nearest_package_manifest(ctx.package_manifests, from_file)?
.package_json
.workspace_alias_target(&alias)?;
let is_project_package = ctx.workspace_roots.contains_key(target)
|| ctx
.package_manifests
.iter()
.any(|manifest| manifest.name.as_deref() == Some(target));
if target == alias || !is_project_package {
return None;
}
Some(format!("{target}{}", &specifier[alias.len()..]))
}
pub(super) fn try_aliased_workspace_package_fallback(
ctx: &ResolveContext<'_>,
from_file: &Path,
specifier: &str,
style_context: bool,
) -> Option<ResolveResult> {
let aliased = aliased_specifier(ctx, from_file, specifier);
workspace_fallback_through_alias(ctx, specifier, aliased.as_deref(), style_context)
}
fn workspace_fallback_through_alias(
ctx: &ResolveContext<'_>,
specifier: &str,
aliased: Option<&str>,
style_context: bool,
) -> Option<ResolveResult> {
let Some(aliased) = aliased else {
return try_workspace_package_fallback(ctx, specifier, style_context);
};
let alias = extract_package_name(specifier);
let result = try_workspace_package_fallback(ctx, aliased, style_context)?;
Some(match result {
ResolveResult::InternalPackageModule { file_id, .. } => {
ResolveResult::InternalPackageModule {
file_id,
package_name: alias,
}
}
ResolveResult::CommonJsInternalPackageModule { file_id, .. } => {
ResolveResult::CommonJsInternalPackageModule {
file_id,
package_name: alias,
}
}
ResolveResult::NpmPackage(_) => ResolveResult::NpmPackage(alias),
ResolveResult::CommonJsNpmPackage(_) => ResolveResult::CommonJsNpmPackage(alias),
other => other,
})
}
pub(super) fn resolve_failed_bare_package_specifier(
ctx: &ResolveContext<'_>,
from_file: &Path,
specifier: &str,
style_context: bool,
matches_tsconfig_path_alias: bool,
) -> ResolveResult {
let aliased = aliased_specifier(ctx, from_file, specifier);
if let Some(result) =
workspace_fallback_through_alias(ctx, specifier, aliased.as_deref(), style_context)
{
return result;
}
if matches_tsconfig_path_alias {
return ResolveResult::Unresolvable(specifier.to_string());
}
let pkg_name = extract_package_name(specifier);
let lookup = aliased.map_or_else(
|| pkg_name.clone(),
|aliased| extract_package_name(&aliased),
);
if ctx.workspace_roots.contains_key(lookup.as_str())
|| ctx
.package_manifests
.iter()
.any(|manifest| manifest.name.as_deref() == Some(lookup.as_str()))
{
ResolveResult::Unresolvable(specifier.to_string())
} else {
ResolveResult::NpmPackage(pkg_name)
}
}