use std::{io, path::PathBuf, sync::Arc};
use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Error)]
pub enum ResolveError {
#[error("Path is ignored {0}")]
Ignored(PathBuf),
#[error("Cannot find module '{0}'")]
NotFound(String),
#[error("Tsconfig not found {0}")]
TsconfigNotFound(PathBuf),
#[error("{0}")]
IOError(IOError),
#[error("Builtin module {0}")]
Builtin(String),
#[error("All of the aliased extension are not found")]
ExtensionAlias,
#[error("{0}")]
Specifier(SpecifierError),
#[error("{0:?}")]
JSON(JSONError),
#[error(r#"Path "{0}" restricted by {0}"#)]
Restriction(PathBuf, PathBuf),
#[error(r#"Invalid module "{0}" specifier is not a valid subpath for the "exports" resolution of {1}"#)]
InvalidModuleSpecifier(String, PathBuf),
#[error(r#"Invalid "exports" target "{0}" defined for '{1}' in the package config {2}"#)]
InvalidPackageTarget(String, String, PathBuf),
#[error(r#"Package subpath '{0}' is not defined by "exports" in {1}"#)]
PackagePathNotExported(String, PathBuf),
#[error(r#"Invalid package config "{0}", "exports" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only."#)]
InvalidPackageConfig(PathBuf),
#[error(r#"Default condition should be last one in "{0}""#)]
InvalidPackageConfigDefault(PathBuf),
#[error(r#"Expecting folder to folder mapping. "{0}" should end with "/"#)]
InvalidPackageConfigDirectory(PathBuf),
#[error(r#"Package import specifier "{0}" is not defined in package {1}"#)]
PackageImportNotDefined(String, PathBuf),
#[error("{0} is unimplemented")]
Unimplemented(&'static str),
#[error("Recursion in resolving")]
Recursion,
}
impl ResolveError {
pub fn is_ignore(&self) -> bool {
matches!(self, Self::Ignored(_))
}
pub(crate) fn from_serde_json_error(path: PathBuf, error: &serde_json::Error) -> Self {
Self::JSON(JSONError {
path,
message: error.to_string(),
line: error.line(),
column: error.column(),
})
}
}
#[derive(Debug, Clone, Eq, PartialEq, Error)]
pub enum SpecifierError {
#[error("The specifiers must be a non-empty string. Received ''")]
Empty,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct JSONError {
pub path: PathBuf,
pub message: String,
pub line: usize,
pub column: usize,
}
#[derive(Debug, Clone, Error)]
#[error("{0}")]
pub struct IOError(Arc<io::Error>);
impl PartialEq for IOError {
fn eq(&self, other: &Self) -> bool {
self.0.kind() == other.0.kind()
}
}
impl From<IOError> for std::io::Error {
fn from(error: IOError) -> Self {
let io_error = error.0.as_ref();
Self::new(io_error.kind(), io_error.to_string())
}
}
impl From<io::Error> for ResolveError {
fn from(err: io::Error) -> Self {
Self::IOError(IOError(Arc::new(err)))
}
}