async-graphql/src/error.rs
2020-03-21 09:32:13 +08:00

217 lines
4.8 KiB
Rust

use crate::Error;
use graphql_parser::query::Value;
use graphql_parser::Pos;
use std::fmt::{Debug, Display, Formatter};
/// Error for query parser
#[derive(Debug, Error)]
#[error("{0}")]
pub struct QueryParseError(pub(crate) String);
/// Error for query
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum QueryError {
#[error("Not supported.")]
NotSupported,
#[error("Expected type \"{expect}\", found {actual}.")]
ExpectedType {
/// Expect input type
expect: String,
/// Actual input type
actual: Value,
},
#[error("Expected type \"{expect}\", found {actual}.")]
ExpectedJsonType {
/// Expect input JSON type
expect: String,
/// Actual input JSON type
actual: serde_json::Value,
},
#[error("Cannot query field \"{field_name}\" on type \"{object}\".")]
FieldNotFound {
/// Field name
field_name: String,
/// Object name
object: String,
},
#[error("Missing operation")]
MissingOperation,
#[error("Unknown operation named \"{name}\"")]
UnknownOperationNamed {
/// Operation name for query
name: String,
},
#[error("Type \"{object}\" must have a selection of subfields.")]
MustHaveSubFields {
/// Object name
object: String,
},
#[error("Schema is not configured for mutations.")]
NotConfiguredMutations,
#[error("Schema is not configured for subscriptions.")]
NotConfiguredSubscriptions,
#[error("Invalid value for enum \"{ty}\".")]
InvalidEnumValue {
/// Enum type name
ty: String,
/// Enum value
value: String,
},
#[error("Required field \"{field_name}\" for InputObject \"{object}\" does not exist.")]
RequiredField {
/// field name
field_name: String,
/// object name
object: &'static str,
},
#[error("Variable \"${var_name}\" is not defined")]
VarNotDefined {
/// Variable name
var_name: String,
},
#[error(
"Directive \"{directive}\" argument \"{arg_name}\" of type \"{arg_type}\" is required, but it was not provided."
)]
RequiredDirectiveArgs {
/// Directive name
directive: &'static str,
/// Argument name
arg_name: &'static str,
/// Argument type
arg_type: &'static str,
},
#[error("Unknown directive \"{name}\".")]
UnknownDirective {
/// Directive name
name: String,
},
#[error("Unknown fragment \"{name}\".")]
UnknownFragment {
// Fragment name
name: String,
},
#[error("Object \"{object}\" does not implement interface \"{interface}\"")]
NotImplementedInterface {
/// Object name
object: String,
/// Interface name
interface: String,
},
#[error("Unrecognized inline fragment \"{name}\" on type \"{object}\"")]
UnrecognizedInlineFragment {
/// Object name
object: String,
/// Inline fragment name
name: String,
},
#[error("Argument \"{field_name}\" must be a non-negative integer")]
ArgumentMustBeNonNegative {
/// Field name
field_name: String,
},
#[error("Invalid global id")]
InvalidGlobalID,
#[error("Invalid global id, expected type \"{expect}\", found {actual}.")]
InvalidGlobalIDType {
/// Expect type
expect: String,
/// Actual type
actual: String,
},
}
/// Creates a wrapper with an error location
#[allow(missing_docs)]
pub trait ErrorWithPosition {
type Result;
fn with_position(self, position: Pos) -> PositionError;
}
impl<T: Into<Error>> ErrorWithPosition for T {
type Result = PositionError;
fn with_position(self, position: Pos) -> PositionError {
PositionError {
position,
inner: self.into(),
}
}
}
/// A wrapper with the wrong location
#[allow(missing_docs)]
#[derive(Debug, Error)]
pub struct PositionError {
pub position: Pos,
pub inner: Error,
}
impl PositionError {
#[allow(missing_docs)]
pub fn new(position: Pos, inner: Error) -> Self {
Self { position, inner }
}
#[allow(missing_docs)]
pub fn into_inner(self) -> Error {
self.inner
}
}
impl Display for PositionError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.inner)
}
}
#[derive(Debug)]
pub struct RuleError {
pub locations: Vec<Pos>,
pub message: String,
}
#[derive(Debug, Error)]
pub struct RuleErrors {
pub errors: Vec<RuleError>,
}
impl Display for RuleErrors {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for error in &self.errors {
writeln!(f, "{}", error.message)?;
}
Ok(())
}
}