diff --git a/crates/nassun/src/error.rs b/crates/nassun/src/error.rs index b332e386..53970f8c 100644 --- a/crates/nassun/src/error.rs +++ b/crates/nassun/src/error.rs @@ -9,79 +9,106 @@ use thiserror::Error; /// Error type returned by all API calls. #[derive(Error, Debug, Diagnostic)] pub enum NassunError { - /// Something went wrong while fetching a package. + /// A given package exists, but the version that the specifier resolved to + /// does not. + /// + /// Check that the version or range you're requesting actually exists and + /// try again. #[error("Package for `{0}` was found, but resolved version `{1}` does not exist.")] #[diagnostic( code(nassun::missing_version), + url(docsrs), help("Try using `oro view` to see what versions are available") )] MissingVersion(PackageSpec, Version), - /// Something went wrong while trying to parse a PackageArg + /// Something went wrong while trying to parse a PackageSpec. #[error(transparent)] #[diagnostic(transparent)] PackageSpecError(#[from] oro_package_spec::PackageSpecError), + /// Failed to read a directory dependency. Refer to the error message for + /// more details. #[error("{0}")] - #[diagnostic(code(nassun::dir::read))] + #[diagnostic(code(nassun::dir::read), url(docsrs))] DirReadError(#[source] std::io::Error, PathBuf), + /// An io-related error occurred while executing git. #[error("Failed to execute git subprocess. {0}")] - #[diagnostic(code(nassun::git::clone::io))] + #[diagnostic(code(nassun::git::clone::io), url(docsrs))] GitIoError(#[source] std::io::Error), + /// An error occurred while trying to clone a repository. #[error("Failed to clone repository at `{0}`")] - #[diagnostic(code(nassun::git::clone::repo))] + #[diagnostic(code(nassun::git::clone::repo), url(docsrs))] GitCloneError(String), + /// An error occurred while trying to checkout a repository. #[error("Failed to check out `{0}#{1}`")] - #[diagnostic(code(nassun::git::checkout::repo))] + #[diagnostic(code(nassun::git::checkout::repo), url(docsrs))] GitCheckoutError(String, String), + /// Failed to extract a tarball while doing a certain IO operation. Refer + /// to the error message for more details. #[error("Failed to extract tarball while {2}{}", if let Some(path) = .1 { format!(" (file: {})", path.to_string_lossy()) } else { "".to_string() })] - #[diagnostic(code(nassun::io::extract))] + #[diagnostic(code(nassun::io::extract), url(docsrs))] ExtractIoError(#[source] std::io::Error, Option, String), + /// Failed to extract a tarball to the cache. Refer to the error message + /// for more details. #[cfg(not(target_arch = "wasm32"))] #[error("Failed to extract tarball to cache. {0}{}", if let Some(path) = .1 { format!(" (file: {})", path.to_string_lossy()) } else { "".to_string() })] - #[diagnostic(code(nassun::cache::extract))] + #[diagnostic(code(nassun::cache::extract), url(docsrs))] ExtractCacheError(#[source] cacache::Error, Option), + /// A generic IO error occurred. Refer tot he error message for more + /// details. #[error(transparent)] - #[diagnostic(code(nassun::io::generic))] + #[diagnostic(code(nassun::io::generic), url(docsrs))] IoError(#[from] std::io::Error), + /// A generic oro-client error. #[error(transparent)] #[diagnostic(transparent)] OroClientError(#[from] oro_client::OroClientError), + /// A generic serde error. #[error(transparent)] - #[diagnostic(code(nassun::serde))] + #[diagnostic(code(nassun::serde), url(docsrs))] SerdeError(#[from] serde_json::Error), + /// Failed to parse a URL. #[error(transparent)] - #[diagnostic(code(nassun::bad_url))] + #[diagnostic(code(nassun::bad_url), url(docsrs))] UrlError(#[from] url::ParseError), + /// Failed to parse a package integrity string. #[error(transparent)] - #[diagnostic(code(nassun::integrity_parse_error))] + #[diagnostic(code(nassun::integrity_parse_error), url(docsrs))] IntegrityError(#[from] ssri::Error), + /// There's no tarball specified as part of the package metadata for a + /// given package. This is likely a bug in the registry. #[error("Package metadata for {0} is missing a package tarball URL.")] - #[diagnostic(code(nassun::no_tarball))] + #[diagnostic(code(nassun::no_tarball), url(docsrs))] NoTarball(String, PackageSpec, Box), + /// No matching version could be found for a given specifier. Make sure + /// that the version, range, or dist-tag you requested actually exists. + /// + /// Using `oro view` can help. #[error("No matching `{name}` version found for spec `{spec}`.")] #[diagnostic( code(resolver::no_matching_version), + url(docsrs), // TODO: format help string using variables? help("Try using `oro view` to see what versions are available") )] @@ -91,36 +118,51 @@ pub enum NassunError { versions: Vec, }, + /// Generic serde-wasm-bindgen error. #[cfg(target_arch = "wasm32")] #[error(transparent)] - #[diagnostic(code(node_maintainer::serde_wasm_bindgen::error))] + #[diagnostic(code(node_maintainer::serde_wasm_bindgen::error), url(docsrs))] SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error), + /// Failed to find git in the user's `$PATH`. + /// + /// Make sure git is installed and visible from the executing shell's `$PATH`. #[cfg(not(target_arch = "wasm32"))] #[error(transparent)] #[diagnostic( code(nassun::which_git_failure), + url(docsrs), help("Are you sure git is installed and available in your $PATH?") )] WhichGit(#[from] which::Error), - #[error("Only Version, Tag, Range, and Alias package args are supported, but got `{0}`.")] - #[diagnostic(code(nassun::invalid_package_spec))] + /// The version resolver ran into an unexpected package spec. This is + /// almost definitely a bug. + #[error("Only Version, Tag, Range, and Alias package specs are supported, but got `{0}`.")] + #[diagnostic(code(nassun::invalid_package_spec), url(docsrs))] InvalidPackageSpec(PackageSpec), + /// Some unsupported operation happened while working with a dummy + /// package. This is an internal detail and almost definitely a bug worth + /// reporting. #[error("Unsupported dummy package operation: {0}")] - #[diagnostic(code(nassun::unsupported_dummy_operation))] + #[diagnostic(code(nassun::unsupported_dummy_operation), url(docsrs))] UnsupportedDummyOperation(String), + /// A dummy package was missing a name. This is an internal detail and + /// almost definitely a bug worth reporting. #[error("Dummy package does not have a name.")] - #[diagnostic(code(nassun::dummy_no_name))] + #[diagnostic(code(nassun::dummy_no_name), url(docsrs))] DummyNoName, /// A miscellaneous, usually internal error. This is used mainly to wrap /// either manual InternalErrors, or those using external errors that /// don't implement std::error::Error. + /// + /// If you see this error, please file a bug report so that a better error + /// can take its place. #[error("{0}")] - #[diagnostic(code(nassun::misc))] + #[diagnostic(code(nassun::misc), url(docsrs))] MiscError(String), } diff --git a/crates/node-maintainer/src/error.rs b/crates/node-maintainer/src/error.rs index 2bea1f88..fc0a5f1a 100644 --- a/crates/node-maintainer/src/error.rs +++ b/crates/node-maintainer/src/error.rs @@ -10,82 +10,85 @@ use crate::{NpmPackageLock, NpmPackageLockEntry}; pub enum NodeMaintainerError { /// Unsupported resolved URL scheme #[error("Unsupported resolved URL scheme")] - #[diagnostic(code(node_maintainer::kdl::unsupported_url_scheme))] + #[diagnostic(code(node_maintainer::kdl::unsupported_url_scheme), url(docsrs))] UnsupportedScheme(String), /// Failed to parse a resolved URL while parsing lockfile #[error("Failed to parse a resolved URL while parsing lockfile: {0}")] - #[diagnostic(code(node_maintainer::kdl::url_parse_error))] + #[diagnostic(code(node_maintainer::kdl::url_parse_error), url(docsrs))] UrlParseError(String, #[source] url::ParseError), /// Failed to parse a Semver string. #[error("Failed to parse a Semver string.")] - #[diagnostic(code(node_maintainer::kdl::semver_parse_error))] + #[diagnostic(code(node_maintainer::kdl::semver_parse_error), url(docsrs))] SemverParseError(#[from] node_semver::SemverError), /// Missing version for NPM package entry in lockfile. #[error("Missing version for NPM package entry in lockfile.")] - #[diagnostic(code(node_maintainer::kdl::missing_version))] + #[diagnostic(code(node_maintainer::kdl::missing_version), url(docsrs))] MissingVersion, /// Missing resolution for package entry in lockfile. #[error("Missing version for NPM package entry in lockfile.")] - #[diagnostic(code(node_maintainer::kdl::missing_version))] + #[diagnostic(code(node_maintainer::kdl::missing_version), url(docsrs))] MissingResolution, /// Failed to parse an integrity value. #[error(transparent)] - #[diagnostic(code(node_maintainer::kdl::integrity_parse_error))] + #[diagnostic(code(node_maintainer::kdl::integrity_parse_error), url(docsrs))] IntegrityParseError(#[from] ssri::Error), /// Failed to parse an integrity value while loading lockfile. #[error("Failed to parse an integrity value while loading lockfile node:\n{0}")] - #[diagnostic(code(node_maintainer::kdl::integrity_parse_error))] + #[diagnostic(code(node_maintainer::kdl::integrity_parse_error), url(docsrs))] KdlLockfileIntegrityParseError(KdlNode, #[source] ssri::Error), /// Missing package node name. #[error("Missing package node name:\n{0}")] - #[diagnostic(code(node_maintainer::kdl::missing_node_name))] + #[diagnostic(code(node_maintainer::kdl::missing_node_name), url(docsrs))] KdlLockMissingName(KdlNode), /// Missing package node name. #[error("Missing package name:\n{0:#?}")] - #[diagnostic(code(node_maintainer::npm::missing_name))] + #[diagnostic(code(node_maintainer::npm::missing_name), url(docsrs))] NpmLockMissingName(Box), /// Failed to parse an integrity value while loading NPM lockfile. #[error("Failed to parse an integrity value while loading lockfile node:\n{0:#?}")] - #[diagnostic(code(node_maintainer::npm::integrity_parse_error))] + #[diagnostic(code(node_maintainer::npm::integrity_parse_error), url(docsrs))] NpmLockfileIntegrityParseError(Box, #[source] ssri::Error), /// Unsupported NPM Package Lock version. #[error("Unsupported NPM Package Lock version: {0}")] - #[diagnostic(code(node_maintainer::npm::unsupported_package_lock_Version))] + #[diagnostic( + code(node_maintainer::npm::unsupported_package_lock_Version), + url(docsrs) + )] NpmUnsupportedPackageLockVersion(u64), /// No root node in KDL lockfile. #[error("No root node in KDL lockfile.")] - #[diagnostic(code(node_maintainer::kdl::missing_root))] + #[diagnostic(code(node_maintainer::kdl::missing_root), url(docsrs))] KdlLockMissingRoot(KdlDocument), /// No root node in NPM lockfile. #[error("No root package in NPM lockfile.")] - #[diagnostic(code(node_maintainer::npm::missing_root))] + #[diagnostic(code(node_maintainer::npm::missing_root), url(docsrs))] NpmLockMissingRoot(NpmPackageLock), /// Error parsing lockfile. #[error(transparent)] - #[diagnostic(code(node_maintainer::kdl::parse_error))] + #[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))] + #[diagnostic(code(node_maintainer::kdl::invalid_lockfile_version), url(docsrs))] InvalidLockfileVersion, /// Error from serde_wasm_bindgen #[cfg(target_arch = "wasm32")] #[error(transparent)] - #[diagnostic(code(node_maintainer::serde_wasm_bindgen::error))] + #[diagnostic(code(node_maintainer::serde_wasm_bindgen::error), url(docsrs))] SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error), /// Generic package spec error. @@ -95,7 +98,7 @@ pub enum NodeMaintainerError { /// Generic IO Error. #[error(transparent)] - #[diagnostic(code(node_maintainer::io_error))] + #[diagnostic(code(node_maintainer::io_error), url(docsrs))] IoError(#[from] std::io::Error), /// Generic error returned from Nassun. @@ -105,32 +108,41 @@ pub enum NodeMaintainerError { /// Generic serde_json error. #[error(transparent)] - #[diagnostic(code(node_maintainer::serde_json_error))] + #[diagnostic(code(node_maintainer::serde_json_error), url(docsrs))] SerdeJsonError(#[from] serde_json::Error), - /// Generic error + /// Generic error. Refer to the error message for more details. #[error("{0}")] - #[diagnostic(code(node_maintainer::miscellaneous_error))] + #[diagnostic(code(node_maintainer::miscellaneous_error), url(docsrs))] MiscError(String), + /// Failed to send data through mpsc channel. This is likely an internal + /// error of some sort. #[error("Failed to send data through mpsc channel.")] - #[diagnostic(code(node_maintainer::mpsc_error))] + #[diagnostic(code(node_maintainer::mpsc_error), url(docsrs))] TrySendError, + /// Failed to validate a graph. Refer to the error message for more details. #[error("{0}")] - #[diagnostic(code(node_maintainer::graph_error))] + #[diagnostic(code(node_maintainer::graph_error), url(docsrs))] GraphValidationError(String), + /// Got an error while walking `node_modules`. Refer to the error message + /// for specific details. #[cfg(not(target_arch = "wasm32"))] #[error(transparent)] - #[diagnostic(code(node_maintainer::walkdir_error))] + #[diagnostic(code(node_maintainer::walkdir_error), url(docsrs))] WalkDirError(#[from] walkdir::Error), + /// Failed to read `package.json` during the build step. Refer to the + /// error message for more details. #[cfg(not(target_arch = "wasm32"))] #[error("Failed to read manifest during build step, at {}", .0.display())] - #[diagnostic(code(node_maintainer::build_manifest_read_error))] + #[diagnostic(code(node_maintainer::build_manifest_read_error), url(docsrs))] BuildManifestReadError(std::path::PathBuf, #[source] std::io::Error), + /// Some error occurred while running a script. Refer to the error message + /// for more details. #[cfg(not(target_arch = "wasm32"))] #[error(transparent)] #[diagnostic(transparent)] diff --git a/crates/oro-client/src/error.rs b/crates/oro-client/src/error.rs index 2a0b76cc..5ec864ab 100644 --- a/crates/oro-client/src/error.rs +++ b/crates/oro-client/src/error.rs @@ -4,17 +4,22 @@ use thiserror::Error; #[derive(Debug, Error, Diagnostic)] pub enum OroClientError { + /// An invalid URL was provided. #[error(transparent)] - #[diagnostic(code(oro_client::url_parse_error))] + #[diagnostic(code(oro_client::url_parse_error), url(docsrs))] UrlParseError(#[from] url::ParseError), + /// The package was not found in the registry. + /// + /// Make sure the package name is spelled correctly and that you've + /// configured the right registry to fetch it from. #[error("Package `{1}` was not found in registry {0}.")] - #[diagnostic(code(oro_client::package_not_found))] + #[diagnostic(code(oro_client::package_not_found), url(docsrs))] PackageNotFound(Url, String), /// Got some bad JSON we couldn't parse. #[error("Received some unexpected JSON. Unable to parse.")] - #[diagnostic(code(oro_client::bad_json))] + #[diagnostic(code(oro_client::bad_json), url(docsrs))] BadJson { source: serde_json::Error, url: String, @@ -24,13 +29,17 @@ pub enum OroClientError { err_loc: (usize, usize), }, + /// A generic request error happened while making a request. Refer to the + /// error message for more details. #[error(transparent)] - #[diagnostic(code(oro_client::request_error))] + #[diagnostic(code(oro_client::request_error), url(docsrs))] RequestError(#[from] reqwest::Error), + /// A generic request middleware error happened while making a request. + /// Refer to the error message for more details. #[cfg(not(target_arch = "wasm32"))] #[error(transparent)] - #[diagnostic(code(oro_client::request_middleware_error))] + #[diagnostic(code(oro_client::request_middleware_error), url(docsrs))] RequestMiddlewareError(#[from] reqwest_middleware::Error), } diff --git a/crates/oro-config/src/error.rs b/crates/oro-config/src/error.rs index ec6dc569..c6ec0f33 100644 --- a/crates/oro-config/src/error.rs +++ b/crates/oro-config/src/error.rs @@ -3,11 +3,15 @@ use thiserror::Error; #[derive(Debug, Error, Diagnostic)] pub enum OroConfigError { + /// A generic config error happened while loading the config. Refer to the + /// error message for more details. #[error(transparent)] - #[diagnostic(code(config::error))] + #[diagnostic(code(oro_config::error), url(docsrs))] ConfigError(#[from] config::ConfigError), + /// A generic error happened while parsing the config. Refer to the error + /// message for more details. #[error(transparent)] - #[diagnostic(code(config::error))] + #[diagnostic(code(oro_config::error), url(docsrs))] ConfigParseError(#[from] Box), } diff --git a/crates/oro-script/src/error.rs b/crates/oro-script/src/error.rs index af94ef1f..209aeafd 100644 --- a/crates/oro-script/src/error.rs +++ b/crates/oro-script/src/error.rs @@ -3,36 +3,53 @@ use thiserror::Error; #[derive(Debug, Error, Diagnostic)] pub enum OroScriptError { + /// Generic IO-related error. Refer to the error message for more details. #[error(transparent)] - #[diagnostic(code(oro_script::io_error))] + #[diagnostic(code(oro_script::io_error), url(docsrs))] IoError(#[from] std::io::Error), + /// Generic serde-related error. Refer to the error message for more + /// details. #[error(transparent)] - #[diagnostic(code(oro_script::serde_error))] + #[diagnostic(code(oro_script::serde_error), url(docsrs))] SerdeError(#[from] serde_json::Error), + /// Failed to spawn child process when executing a script. Refer to the + /// error message for more details. #[error("Failed to spawn child process.")] - #[diagnostic(code(oro_script::spawn_error))] + #[diagnostic(code(oro_script::spawn_error), url(docsrs))] SpawnError(#[source] std::io::Error), + /// Failed to find an event in a package's `package.json`. This means, for + /// example, that a `"postinstall"` script was requested, but not actually + /// present. #[error("Failed to find event `{0}` in package.")] - #[diagnostic(code(oro_script::missing_event))] + #[diagnostic(code(oro_script::missing_event), url(docsrs))] MissingEvent(String), - #[error(transparent)] - #[diagnostic(code(oro_script::join_path_error))] + /// Failed to join new contents of PATH variable while trying to add a + /// `node_modules/.bin` entry to the PATH. + /// + /// When executing a script, the current package and their ancestors get + /// their `node_modules/.bin` directories added to the PATH. This error + /// means something went wrong while putting the variable back together. + /// For more details on what may have happened, refer to the error + /// message. + #[error("Failed to join new contents of PATH variable while trying to add a `node_modules/.bin` entry to the PATH.")] + #[diagnostic(code(oro_script::join_path_error), url(docsrs))] JoinPathError(#[from] std::env::JoinPathsError), - #[error("Error parsing script: `{0}`")] - #[diagnostic(code(oro_script::parse_error))] - ScriptParseError(String), - + /// Something went wrong while performing an operation on a script's + /// process. For more details, refer to the error message. #[error("Error performing process operation on script.")] - #[diagnostic(code(oro_script::script_process_error))] + #[diagnostic(code(oro_script::script_process_error), url(docsrs))] ScriptProcessError(#[source] std::io::Error), + /// The script terminated with a non-zero exit code, meaning some error + /// happened with the script itself. Details may have been logged in the + /// log file/stdout/stderr. #[error("Script exited with code {}", .0.code().unwrap_or(-1))] - #[diagnostic(code(oro_script::script_error))] + #[diagnostic(code(oro_script::script_error), url(docsrs))] ScriptError(std::process::ExitStatus, Option>, Option>), } diff --git a/src/commands/remove.rs b/src/commands/remove.rs index 9a44a3e7..e133c8e6 100644 --- a/src/commands/remove.rs +++ b/src/commands/remove.rs @@ -13,6 +13,8 @@ enum RemoveCmdError { /// Invalid package name. Only package names should be passed to `oro /// remove`, but you passed either a package specifier or an invalid /// package name. + /// + /// Try passing the package name as it appears in your package.json. #[error("{0} is not a valid package name. Only package names should be passed to `oro remove`, but you passed either a non-NPM package specifier or an invalid package name.")] #[diagnostic( code(oro::remove::invalid_package_name),