2020-04-02 02:21:04 +00:00
|
|
|
use graphql_parser::query::{ParseError, Value};
|
2020-03-01 10:54:34 +00:00
|
|
|
use graphql_parser::Pos;
|
2020-04-02 02:21:04 +00:00
|
|
|
use std::error::Error as StdError;
|
|
|
|
use std::fmt::Debug;
|
|
|
|
|
|
|
|
/// FieldError type
|
|
|
|
pub struct FieldError(anyhow::Error, Option<serde_json::Value>);
|
|
|
|
|
|
|
|
impl FieldError {
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn into_error(self, pos: Pos) -> Error {
|
|
|
|
Error::Query {
|
|
|
|
pos,
|
|
|
|
path: None,
|
|
|
|
err: QueryError::FieldError {
|
|
|
|
err: self.0,
|
|
|
|
extended_error: self.1,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2020-03-01 10:54:34 +00:00
|
|
|
|
2020-04-02 02:21:04 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn into_error_with_path(self, pos: Pos, path: serde_json::Value) -> Error {
|
|
|
|
Error::Query {
|
|
|
|
pos,
|
|
|
|
path: Some(path),
|
|
|
|
err: QueryError::FieldError {
|
|
|
|
err: self.0,
|
|
|
|
extended_error: self.1,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// FieldResult type
|
|
|
|
pub type FieldResult<T> = std::result::Result<T, FieldError>;
|
|
|
|
|
|
|
|
impl<E> From<E> for FieldError
|
|
|
|
where
|
|
|
|
E: StdError + Send + Sync + 'static,
|
|
|
|
{
|
|
|
|
fn from(err: E) -> Self {
|
|
|
|
FieldError(anyhow::Error::from(err), None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(missing_docs)]
|
|
|
|
pub trait ResultExt<T, E>
|
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
E: StdError + Send + Sync + 'static,
|
|
|
|
{
|
|
|
|
fn extend_err<CB>(self, cb: CB) -> FieldResult<T>
|
|
|
|
where
|
|
|
|
CB: FnOnce(&E) -> serde_json::Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, E> ResultExt<T, E> for std::result::Result<T, E>
|
|
|
|
where
|
|
|
|
E: StdError + Send + Sync + 'static,
|
|
|
|
{
|
|
|
|
fn extend_err<C>(self, cb: C) -> FieldResult<T>
|
|
|
|
where
|
|
|
|
C: FnOnce(&E) -> serde_json::Value,
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
Err(err) => {
|
|
|
|
let extended_err = cb(&err);
|
|
|
|
Err(FieldError(err.into(), Some(extended_err)))
|
|
|
|
}
|
|
|
|
Ok(value) => Ok(value),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-01 10:54:34 +00:00
|
|
|
|
2020-03-20 03:56:08 +00:00
|
|
|
/// Error for query
|
2020-03-01 10:54:34 +00:00
|
|
|
#[derive(Debug, Error)]
|
2020-03-20 03:56:08 +00:00
|
|
|
#[allow(missing_docs)]
|
2020-03-01 13:35:39 +00:00
|
|
|
pub enum QueryError {
|
2020-03-01 10:54:34 +00:00
|
|
|
#[error("Not supported.")]
|
|
|
|
NotSupported,
|
|
|
|
|
|
|
|
#[error("Expected type \"{expect}\", found {actual}.")]
|
2020-03-20 03:56:08 +00:00
|
|
|
ExpectedType {
|
|
|
|
/// Expect input type
|
|
|
|
expect: String,
|
|
|
|
|
|
|
|
/// Actual input type
|
|
|
|
actual: Value,
|
|
|
|
},
|
2020-03-01 10:54:34 +00:00
|
|
|
|
2020-03-01 16:52:05 +00:00
|
|
|
#[error("Expected type \"{expect}\", found {actual}.")]
|
|
|
|
ExpectedJsonType {
|
2020-03-20 03:56:08 +00:00
|
|
|
/// Expect input JSON type
|
2020-03-03 11:15:18 +00:00
|
|
|
expect: String,
|
2020-03-20 03:56:08 +00:00
|
|
|
|
|
|
|
/// Actual input JSON type
|
2020-03-01 16:52:05 +00:00
|
|
|
actual: serde_json::Value,
|
|
|
|
},
|
|
|
|
|
2020-03-01 10:54:34 +00:00
|
|
|
#[error("Cannot query field \"{field_name}\" on type \"{object}\".")]
|
2020-03-20 03:56:08 +00:00
|
|
|
FieldNotFound {
|
|
|
|
/// Field name
|
|
|
|
field_name: String,
|
|
|
|
|
|
|
|
/// Object name
|
|
|
|
object: String,
|
|
|
|
},
|
2020-03-01 10:54:34 +00:00
|
|
|
|
2020-03-14 03:46:20 +00:00
|
|
|
#[error("Missing operation")]
|
|
|
|
MissingOperation,
|
|
|
|
|
2020-03-01 10:54:34 +00:00
|
|
|
#[error("Unknown operation named \"{name}\"")]
|
2020-03-20 03:56:08 +00:00
|
|
|
UnknownOperationNamed {
|
|
|
|
/// Operation name for query
|
|
|
|
name: String,
|
|
|
|
},
|
2020-03-01 10:54:34 +00:00
|
|
|
|
|
|
|
#[error("Type \"{object}\" must have a selection of subfields.")]
|
2020-03-20 03:56:08 +00:00
|
|
|
MustHaveSubFields {
|
|
|
|
/// Object name
|
|
|
|
object: String,
|
|
|
|
},
|
2020-03-01 10:54:34 +00:00
|
|
|
|
|
|
|
#[error("Schema is not configured for mutations.")]
|
|
|
|
NotConfiguredMutations,
|
|
|
|
|
2020-03-17 09:26:59 +00:00
|
|
|
#[error("Schema is not configured for subscriptions.")]
|
|
|
|
NotConfiguredSubscriptions,
|
|
|
|
|
2020-03-02 00:24:49 +00:00
|
|
|
#[error("Invalid value for enum \"{ty}\".")]
|
2020-03-20 03:56:08 +00:00
|
|
|
InvalidEnumValue {
|
|
|
|
/// Enum type name
|
|
|
|
ty: String,
|
|
|
|
|
|
|
|
/// Enum value
|
|
|
|
value: String,
|
|
|
|
},
|
2020-03-01 13:35:39 +00:00
|
|
|
|
|
|
|
#[error("Required field \"{field_name}\" for InputObject \"{object}\" does not exist.")]
|
|
|
|
RequiredField {
|
2020-03-20 03:56:08 +00:00
|
|
|
/// field name
|
2020-03-01 13:35:39 +00:00
|
|
|
field_name: String,
|
2020-03-20 03:56:08 +00:00
|
|
|
|
|
|
|
/// object name
|
2020-03-01 13:35:39 +00:00
|
|
|
object: &'static str,
|
|
|
|
},
|
|
|
|
|
|
|
|
#[error("Variable \"${var_name}\" is not defined")]
|
2020-03-20 03:56:08 +00:00
|
|
|
VarNotDefined {
|
|
|
|
/// Variable name
|
|
|
|
var_name: String,
|
|
|
|
},
|
2020-03-04 06:24:44 +00:00
|
|
|
|
|
|
|
#[error(
|
|
|
|
"Directive \"{directive}\" argument \"{arg_name}\" of type \"{arg_type}\" is required, but it was not provided."
|
|
|
|
)]
|
|
|
|
RequiredDirectiveArgs {
|
2020-03-20 03:56:08 +00:00
|
|
|
/// Directive name
|
2020-03-04 06:24:44 +00:00
|
|
|
directive: &'static str,
|
2020-03-20 03:56:08 +00:00
|
|
|
|
|
|
|
/// Argument name
|
2020-03-04 06:24:44 +00:00
|
|
|
arg_name: &'static str,
|
2020-03-20 03:56:08 +00:00
|
|
|
|
|
|
|
/// Argument type
|
2020-03-04 06:24:44 +00:00
|
|
|
arg_type: &'static str,
|
|
|
|
},
|
|
|
|
|
|
|
|
#[error("Unknown directive \"{name}\".")]
|
2020-03-20 03:56:08 +00:00
|
|
|
UnknownDirective {
|
|
|
|
/// Directive name
|
|
|
|
name: String,
|
|
|
|
},
|
2020-03-05 07:50:57 +00:00
|
|
|
|
|
|
|
#[error("Unknown fragment \"{name}\".")]
|
2020-03-20 03:56:08 +00:00
|
|
|
UnknownFragment {
|
|
|
|
// Fragment name
|
|
|
|
name: String,
|
|
|
|
},
|
2020-03-07 02:39:55 +00:00
|
|
|
|
|
|
|
#[error("Object \"{object}\" does not implement interface \"{interface}\"")]
|
2020-03-20 03:56:08 +00:00
|
|
|
NotImplementedInterface {
|
|
|
|
/// Object name
|
|
|
|
object: String,
|
|
|
|
|
|
|
|
/// Interface name
|
|
|
|
interface: String,
|
|
|
|
},
|
2020-03-07 02:39:55 +00:00
|
|
|
|
|
|
|
#[error("Unrecognized inline fragment \"{name}\" on type \"{object}\"")]
|
2020-03-20 03:56:08 +00:00
|
|
|
UnrecognizedInlineFragment {
|
|
|
|
/// Object name
|
|
|
|
object: String,
|
|
|
|
|
|
|
|
/// Inline fragment name
|
|
|
|
name: String,
|
|
|
|
},
|
2020-03-19 09:20:12 +00:00
|
|
|
|
2020-04-02 02:21:04 +00:00
|
|
|
#[error("Too complex")]
|
2020-03-25 07:07:16 +00:00
|
|
|
TooComplex,
|
|
|
|
|
2020-04-02 02:21:04 +00:00
|
|
|
#[error("Too deep")]
|
2020-03-25 07:07:16 +00:00
|
|
|
TooDeep,
|
2020-03-01 10:54:34 +00:00
|
|
|
|
2020-04-02 02:21:04 +00:00
|
|
|
#[error("Failed to resolve field: {err}")]
|
|
|
|
FieldError {
|
|
|
|
err: anyhow::Error,
|
|
|
|
extended_error: Option<serde_json::Value>,
|
|
|
|
},
|
2020-03-01 10:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-04-02 02:21:04 +00:00
|
|
|
impl QueryError {
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn into_error(self, pos: Pos) -> Error {
|
|
|
|
Error::Query {
|
|
|
|
pos,
|
|
|
|
path: None,
|
|
|
|
err: self,
|
2020-03-01 10:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-08 12:35:36 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct RuleError {
|
|
|
|
pub locations: Vec<Pos>,
|
|
|
|
pub message: String,
|
|
|
|
}
|
|
|
|
|
2020-04-02 02:21:04 +00:00
|
|
|
impl From<ParseError> for Error {
|
|
|
|
fn from(err: ParseError) -> Self {
|
|
|
|
Error::Parse {
|
|
|
|
message: err.to_string(),
|
2020-03-08 12:35:36 +00:00
|
|
|
}
|
2020-03-29 14:31:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(missing_docs)]
|
2020-04-02 02:21:04 +00:00
|
|
|
#[derive(Debug, Error)]
|
|
|
|
pub enum Error {
|
|
|
|
#[error("Parse error: {message}")]
|
|
|
|
Parse { message: String },
|
|
|
|
|
|
|
|
#[error("Query error: {err}")]
|
|
|
|
Query {
|
|
|
|
pos: Pos,
|
|
|
|
path: Option<serde_json::Value>,
|
|
|
|
err: QueryError,
|
|
|
|
},
|
2020-03-29 14:31:45 +00:00
|
|
|
|
2020-04-02 02:21:04 +00:00
|
|
|
#[error("Rule error")]
|
|
|
|
Rule { errors: Vec<RuleError> },
|
2020-03-29 14:31:45 +00:00
|
|
|
}
|