use futures::channel::mpsc;
use kdl::{KdlDocument, KdlNode};
use miette::Diagnostic;
use thiserror::Error;
use crate::{NpmPackageLock, NpmPackageLockEntry};
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Error, Diagnostic)]
pub enum NodeMaintainerError {
#[error("Unsupported resolved URL scheme")]
#[diagnostic(code(node_maintainer::kdl::unsupported_url_scheme), url(docsrs))]
UnsupportedScheme(String),
#[error("Failed to parse a resolved URL while parsing lockfile: {0}")]
#[diagnostic(code(node_maintainer::kdl::url_parse_error), url(docsrs))]
UrlParseError(String, #[source] url::ParseError),
#[error("Failed to parse a Semver string.")]
#[diagnostic(code(node_maintainer::kdl::semver_parse_error), url(docsrs))]
SemverParseError(#[from] node_semver::SemverError),
#[error("Missing version for NPM package entry in lockfile.")]
#[diagnostic(code(node_maintainer::kdl::missing_version), url(docsrs))]
MissingVersion,
#[error("Missing version for NPM package entry in lockfile.")]
#[diagnostic(code(node_maintainer::kdl::missing_version), url(docsrs))]
MissingResolution,
#[error(transparent)]
#[diagnostic(code(node_maintainer::kdl::integrity_parse_error), url(docsrs))]
IntegrityParseError(#[from] ssri::Error),
#[error("Failed to parse an integrity value while loading lockfile node:\n{0}")]
#[diagnostic(code(node_maintainer::kdl::integrity_parse_error), url(docsrs))]
KdlLockfileIntegrityParseError(KdlNode, #[source] ssri::Error),
#[error("Missing package node name:\n{0}")]
#[diagnostic(code(node_maintainer::kdl::missing_node_name), url(docsrs))]
KdlLockMissingName(KdlNode),
#[error("Missing package name:\n{0:#?}")]
#[diagnostic(code(node_maintainer::npm::missing_name), url(docsrs))]
NpmLockMissingName(Box<NpmPackageLockEntry>),
#[error("Failed to parse an integrity value while loading lockfile node:\n{0:#?}")]
#[diagnostic(code(node_maintainer::npm::integrity_parse_error), url(docsrs))]
NpmLockfileIntegrityParseError(Box<NpmPackageLockEntry>, #[source] ssri::Error),
#[error("Unsupported NPM Package Lock version: {0}")]
#[diagnostic(
code(node_maintainer::npm::unsupported_package_lock_Version),
url(docsrs)
)]
NpmUnsupportedPackageLockVersion(u64),
#[error("No root node in KDL lockfile.")]
#[diagnostic(code(node_maintainer::kdl::missing_root), url(docsrs))]
KdlLockMissingRoot(KdlDocument),
#[error("No root package in NPM lockfile.")]
#[diagnostic(code(node_maintainer::npm::missing_root), url(docsrs))]
NpmLockMissingRoot(NpmPackageLock),
#[error(transparent)]
#[diagnostic(code(node_maintainer::kdl::parse_error), url(docsrs))]
KdlParseError(#[from] kdl::KdlError),
#[error("Invalid lockfile version format.")]
#[diagnostic(code(node_maintainer::kdl::invalid_lockfile_version), url(docsrs))]
InvalidLockfileVersion,
#[cfg(target_arch = "wasm32")]
#[error(transparent)]
#[diagnostic(code(node_maintainer::serde_wasm_bindgen::error), url(docsrs))]
SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error),
#[error(transparent)]
#[diagnostic(transparent)]
PackageSpecError(#[from] oro_package_spec::PackageSpecError),
#[error("{0}")]
#[diagnostic(code(node_maintainer::io_error), url(docsrs))]
IoError(String, #[source] std::io::Error),
#[cfg(not(target_arch = "wasm32"))]
#[error(transparent)]
#[diagnostic(transparent)]
NassunError(#[from] nassun::NassunError),
#[cfg(windows)]
#[error("Failed to create either a symlink or junction from {} to {}.", .0.display(), .1.display())]
#[diagnostic(
code(node_maintainer::junctions_not_supported),
url(docsrs),
help("The isolated linker requires your Windows user to either be able to create symlinks, which requires Administrator privileges, or create junctions, which require an NTFS filesystem, among other things. If you see this message, you might consider switching to the 'hoisted' linker instead.")
)]
JunctionsNotSupported(
std::path::PathBuf,
std::path::PathBuf,
#[source] std::io::Error,
),
#[cfg(target_arch = "wasm32")]
#[error(transparent)]
#[diagnostic(transparent)]
NassunError(#[from] nassun::error::NassunError),
#[error(transparent)]
#[diagnostic(code(node_maintainer::serde_json_error), url(docsrs))]
SerdeJsonError(#[from] serde_json::Error),
#[error("{0}")]
#[diagnostic(code(node_maintainer::miscellaneous_error), url(docsrs))]
MiscError(String),
#[error("Failed to send data through mpsc channel.")]
#[diagnostic(code(node_maintainer::mpsc_error), url(docsrs))]
TrySendError,
#[error("{0}")]
#[diagnostic(code(node_maintainer::graph_error), url(docsrs))]
GraphValidationError(String),
#[cfg(not(target_arch = "wasm32"))]
#[error(transparent)]
#[diagnostic(code(node_maintainer::walkdir_error), url(docsrs))]
WalkDirError(#[from] walkdir::Error),
#[cfg(not(target_arch = "wasm32"))]
#[error("Failed to read manifest during build step, at {}", .0.display())]
#[diagnostic(code(node_maintainer::build_manifest_read_error), url(docsrs))]
BuildManifestReadError(std::path::PathBuf, #[source] std::io::Error),
#[cfg(not(target_arch = "wasm32"))]
#[error(transparent)]
#[diagnostic(transparent)]
OroScriptError(#[from] oro_script::OroScriptError),
#[error("Locked file was requested, but a new dependency tree was resolved that would cause changes to the lockfile. The contents of `package.json` may have changed since the last time the lockfile was updated.")]
#[diagnostic(
code(node_maintainer::lockfile_mismatch),
url(docsrs),
help("Did you modify package.json by hand?")
)]
LockfileMismatch,
}
impl<T> From<mpsc::TrySendError<T>> for NodeMaintainerError {
fn from(_: mpsc::TrySendError<T>) -> Self {
NodeMaintainerError::TrySendError
}
}
pub trait IoContext {
type T;
fn io_context(self, context: impl FnOnce() -> String) -> Result<Self::T, NodeMaintainerError>;
}
impl<T> IoContext for Result<T, std::io::Error> {
type T = T;
fn io_context(self, context: impl FnOnce() -> String) -> Result<Self::T, NodeMaintainerError> {
self.map_err(|e| NodeMaintainerError::IoError(context(), e))
}
}