1use serde::{ser::Error as SerError, Deserialize, Serialize, Serializer};
2
3use crate::util::DisplayVec;
4
5#[non_exhaustive]
6#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, thiserror::Error)]
7pub enum InvalidSchemaError {
8    #[error("Multiple schema errors: {0}")]
9    MultipleErrors(DisplayVec<InvalidSchemaError>),
10
11    #[serde(skip_deserializing, serialize_with = "fail_serialize_schema_parse_error")]
12    #[error("Schema failed to parse.")]
13    SchemaParseError(#[from] async_graphql_parser::Error),
14
15    #[error(
16        "Field \"{0}\" on type \"{1}\" comes from the implementation of interface \"{2}\" \
17        but the field's type {3} is not compatible with the {4} type required by that interface. \
18        The expected type for this field is the {4} type required by the interface, with optional \
19        additional non-null constraints."
20    )]
21    InvalidTypeWideningOfInheritedField(String, String, String, String, String),
22
23    #[error(
24        "Field \"{0}\" on type \"{1}\" comes from the implementation of interface \"{2}\" \
25        but the field's {3} parameter type {4} is not compatible with the {5} type required \
26        by that interface. The expected type for this field parameter is the {5} type required by \
27        the interface, optionally with non-null constraints removed if any are present."
28    )]
29    InvalidTypeNarrowingOfInheritedFieldParameter(String, String, String, String, String, String),
30
31    #[error(
32        "Field \"{0}\" on type \"{1}\" is missing parameter(s) that are required by \
33        the implementation of interface \"{2}\" for this type: {3:?}"
34    )]
35    InheritedFieldMissingParameters(String, String, String, Vec<String>),
36
37    #[error(
38        "Field \"{0}\" on type \"{1}\" contains parameter(s) that are unexpected for \
39        the implementation of interface \"{2}\" for this type: {3:?}"
40    )]
41    InheritedFieldUnexpectedParameters(String, String, String, Vec<String>),
42
43    #[error(
44        "Field \"{0}\" on type \"{1}\" accepts parameter \"{2}\" with type {3}, but gives it \
45        a default value that is not valid for that type: {4}"
46    )]
47    InvalidDefaultValueForFieldParameter(String, String, String, String, String),
48
49    #[error(
50        "The following types have a circular implementation relationship, \
51        which is not allowed: {0:?}"
52    )]
53    CircularImplementsRelationships(Vec<String>),
54
55    #[error(
56        "Type \"{0}\" fails to implement interface \"{2}\", which is required since \"{0}\" \
57        implements \"{1}\" which in turn implements \"{2}\"."
58    )]
59    MissingTransitiveInterfaceImplementation(String, String, String),
60
61    #[error(
62        "Type \"{0}\" implements interface \"{1}\", but is missing field \"{2}\" of type {3} \
63        which is required by that interface."
64    )]
65    MissingRequiredField(String, String, String, String),
66
67    #[error(
72        "Type \"{0}\" defines field \"{1}\" of type {2}, but its origin is ambiguous because \
73        multiple unrelated interfaces implemented by type \"{0}\" all define their own fields \
74        by that name: {3:?}"
75    )]
76    AmbiguousFieldOrigin(String, String, String, Vec<String>),
77
78    #[error(
79        "Type \"{0}\" defines field \"{1}\" which is determined to be a property field because \
80        of its type {2}. Property fields cannot take parameters, but this field takes parameters: \
81        {3:?}"
82    )]
83    PropertyFieldWithParameters(String, String, String, Vec<String>),
84
85    #[error(
86        "Type \"{0}\" defines edge \"{1}\" of type {2}, which is not allowed. Edge types must be \
87        vertex or list of vertex types, with optional nullability. Vertex types in two or more \
88        nested lists are not supported."
89    )]
90    InvalidEdgeType(String, String, String),
91
92    #[error(
93        "Field \"{0}\" of type \"{1}\" appears to represent neither an edge nor a property. \
94        Did you forget to define the type \"{1}\"?"
95    )]
96    UnknownPropertyOrEdgeType(String, String),
97
98    #[error(
99        "The schema's root query type \"{0}\" defines a field \"{1}\" which is determined to \
100        be a property field because of its type {2}. The root query type may only contain \
101        edge fields; property fields are not allowed on the root query type."
102    )]
103    PropertyFieldOnRootQueryType(String, String, String),
104
105    #[error(
106        "Type \"{0}\" defines edge \"{1}\" of type {2}, but that type refers to \
107        the root query type of this schema, which is not supported."
108    )]
109    EdgePointsToRootQueryType(String, String, String),
110
111    #[error(
112        "Type \"{0}\" defines field \"{1}\", but the field prefix \"__\" is reserved \
113        for internal use and cannot be used in schemas."
114    )]
115    ReservedFieldName(String, String),
116
117    #[error(
118        "Type \"{0}\" uses the prefix \"__\" which is reserved \
119        for internal use and cannot be used in schemas."
120    )]
121    ReservedTypeName(String),
122
123    #[error("Type \"{0}\" claims to implement type \"{1}\" which is not defined in this schema.")]
124    ImplementingNonExistentType(String, String),
125
126    #[error(
127        "Type \"{0}\" attempts to implement non-interface type \"{1}\". \
128        Only interfaces can be implemented by other types."
129    )]
130    ImplementingNonInterface(String, String),
131
132    #[error("Type \"{0}\" defines the field \"{1}\" multiple times.")]
133    DuplicateFieldDefinition(String, String),
134
135    #[error("Multiple types or intefaces with the name \"{0}\".")]
136    DuplicateTypeOrInterfaceDefinition(String),
137}
138
139impl From<Vec<InvalidSchemaError>> for InvalidSchemaError {
140    fn from(v: Vec<InvalidSchemaError>) -> Self {
141        assert!(!v.is_empty());
142        if v.len() == 1 {
143            v.into_iter().next().unwrap()
144        } else {
145            Self::MultipleErrors(DisplayVec(v))
146        }
147    }
148}
149
150fn fail_serialize_schema_parse_error<S: Serializer>(
151    _: &async_graphql_parser::Error,
152    _: S,
153) -> Result<S::Ok, S::Error> {
154    Err(S::Error::custom("cannot serialize SchemaParseError error variant"))
155}