1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use serde::{ser::Error as SerError, Deserialize, Serialize, Serializer};

use crate::util::DisplayVec;

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, thiserror::Error)]
pub enum InvalidSchemaError {
    #[error("Multiple schema errors: {0}")]
    MultipleErrors(DisplayVec<InvalidSchemaError>),

    #[serde(skip_deserializing, serialize_with = "fail_serialize_schema_parse_error")]
    #[error("Schema failed to parse.")]
    SchemaParseError(#[from] async_graphql_parser::Error),

    #[error(
        "Field \"{0}\" on type \"{1}\" comes from the implementation of interface \"{2}\" \
        but the field's type {3} is not compatible with the {4} type required by that interface. \
        The expected type for this field is the {4} type required by the interface, with optional \
        additional non-null constraints."
    )]
    InvalidTypeWideningOfInheritedField(String, String, String, String, String),

    #[error(
        "Field \"{0}\" on type \"{1}\" comes from the implementation of interface \"{2}\" \
        but the field's {3} parameter type {4} is not compatible with the {5} type required \
        by that interface. The expected type for this field parameter is the {5} type required by \
        the interface, optionally with non-null constraints removed if any are present."
    )]
    InvalidTypeNarrowingOfInheritedFieldParameter(String, String, String, String, String, String),

    #[error(
        "Field \"{0}\" on type \"{1}\" is missing parameter(s) that are required by \
        the implementation of interface \"{2}\" for this type: {3:?}"
    )]
    InheritedFieldMissingParameters(String, String, String, Vec<String>),

    #[error(
        "Field \"{0}\" on type \"{1}\" contains parameter(s) that are unexpected for \
        the implementation of interface \"{2}\" for this type: {3:?}"
    )]
    InheritedFieldUnexpectedParameters(String, String, String, Vec<String>),

    #[error(
        "Field \"{0}\" on type \"{1}\" accepts parameter \"{2}\" with type {3}, but gives it \
        a default value that is not valid for that type: {4}"
    )]
    InvalidDefaultValueForFieldParameter(String, String, String, String, String),

    #[error(
        "The following types have a circular implementation relationship, \
        which is not allowed: {0:?}"
    )]
    CircularImplementsRelationships(Vec<String>),

    #[error(
        "Type \"{0}\" fails to implement interface \"{2}\", which is required since \"{0}\" \
        implements \"{1}\" which in turn implements \"{2}\"."
    )]
    MissingTransitiveInterfaceImplementation(String, String, String),

    #[error(
        "Type \"{0}\" implements interface \"{1}\", but is missing field \"{2}\" of type {3} \
        which is required by that interface."
    )]
    MissingRequiredField(String, String, String, String),

    /// This may or may not be supported in the future.
    ///
    /// If supported, it will only be supported as an explicit opt-in,
    /// e.g. via an explicit directive on each type where a new ambiguity appears.
    #[error(
        "Type \"{0}\" defines field \"{1}\" of type {2}, but its origin is ambiguous because \
        multiple unrelated interfaces implemented by type \"{0}\" all define their own fields \
        by that name: {3:?}"
    )]
    AmbiguousFieldOrigin(String, String, String, Vec<String>),

    #[error(
        "Type \"{0}\" defines field \"{1}\" which is determined to be a property field because \
        of its type {2}. Property fields cannot take parameters, but this field takes parameters: \
        {3:?}"
    )]
    PropertyFieldWithParameters(String, String, String, Vec<String>),

    #[error(
        "Type \"{0}\" defines edge \"{1}\" of type {2}, which is not allowed. Edge types must be \
        vertex or list of vertex types, with optional nullability. Vertex types in two or more \
        nested lists are not supported."
    )]
    InvalidEdgeType(String, String, String),

    #[error(
        "The schema's root query type \"{0}\" defines a field \"{1}\" which is determined to \
        be a property field because of its type {2}. The root query type may only contain \
        edge fields; property fields are not allowed on the root query type."
    )]
    PropertyFieldOnRootQueryType(String, String, String),

    #[error(
        "Type \"{0}\" defines edge \"{1}\" of type {2}, but that type refers to \
        the root query type of this schema, which is not supported."
    )]
    EdgePointsToRootQueryType(String, String, String),

    #[error(
        "Type \"{0}\" defines field \"{1}\", but the field prefix \"__\" is reserved \
        for internal use and cannot be used in schemas."
    )]
    ReservedFieldName(String, String),

    #[error(
        "Type \"{0}\" uses the prefix \"__\" which is reserved \
        for internal use and cannot be used in schemas."
    )]
    ReservedTypeName(String),

    #[error("Type \"{0}\" claims to implement type \"{1}\" which is not defined in this schema.")]
    ImplementingNonExistentType(String, String),

    #[error(
        "Type \"{0}\" attempts to implement non-interface type \"{1}\". \
        Only interfaces can be implemented by other types."
    )]
    ImplementingNonInterface(String, String),

    #[error("Type \"{0}\" defines the field \"{1}\" multiple times.")]
    DuplicateFieldDefinition(String, String),

    #[error("Multiple types or intefaces with the name \"{0}\".")]
    DuplicateTypeOrInterfaceDefinition(String),
}

impl From<Vec<InvalidSchemaError>> for InvalidSchemaError {
    fn from(v: Vec<InvalidSchemaError>) -> Self {
        assert!(!v.is_empty());
        if v.len() == 1 {
            v.into_iter().next().unwrap()
        } else {
            Self::MultipleErrors(DisplayVec(v))
        }
    }
}

fn fail_serialize_schema_parse_error<S: Serializer>(
    _: &async_graphql_parser::Error,
    _: S,
) -> Result<S::Ok, S::Error> {
    Err(S::Error::custom("cannot serialize SchemaParseError error variant"))
}