@@ -3,8 +3,9 @@ title = "A comprehensive guide to GraphQL API changes"
33author = " Andreas Marek"
44tags = []
55categories = []
6- date = 2022 -02-07T00:00:00+10:00
6+ date = 2021 -02-07T00:00:00+10:00
77toc = " true"
8+ draft = " true"
89+++
910
1011__ Note: this guide aims to be an update document which will be updated if needed.__
@@ -124,7 +125,6 @@ what consequence each change have.
124125
125126Same naming conventions:
126127
127-
128128- the type of a type is called kind. It can be Enum,
129129Scalar, Input Object, Object, Interface or Union.
130130- Argument means arguments for fields and for Directives if
@@ -135,10 +135,15 @@ not explicitly mentioned otherwise.
135135- Schema Directive is a Directive which is a valid for locations in a SDL
136136- Input types are Scalar, Enum, Input Objects.
137137- Output types are Scalar, Enum, Object, Interfaces and Union.
138+ - Composite types are Objects, Interface, Union and Input Objects
139+ - Atomic types are Scalar and Enum
140+
141+ In general we don't consider changes which results in invalid schemas.
142+ For example changing an Input object type to an Interface type results in an invalid schema.
138143
139144List of changes:
140145
141- ## 1. A type is removed.
146+ ## 1. A type is removed
142147When a type is removed every Query which directly uses the type by name becomes invalid.
143148For input types this means a variable declaration becomes invalid:
144149
@@ -159,14 +164,31 @@ For composite output types every query which uses the type as type condition bec
159164When a Scalar or Enum which is used as output type is removed it means the field
160165which returns this Scalar or Enum is either removed or changed in a breaking way.
161166
162- ## 2. The kind of a type is changed.
167+ ## 2. A type is replaced with another type of same name (The kind of a type is changed)
168+
169+ ### 2A: A composite output type is replaced with an atomic type or vice versa
170+
171+ This causes invalid queries as a composite type requires sub selection, while
172+ atomic types don't allow them.
173+
174+ ### 2B: An Input Object is replaced with an atomic type or vice versa
175+
176+ This causes invalid queries as the values of an input object are not
177+ compatible with Enum or Scalar values. One exception is when an Input Object is replaced
178+ with a custom Scalar which allows the same values as the Input Object.
163179
164- Changing the kind of a type means fundamentally changing the guarantee about this type.
180+ ### 2C: A Object or Interface is replaced with a Union
165181
166- Open discussion: changing an Object (which was not used as type in an Union)
167- is maybe not breaking?
182+ This causes invalid queries because Object and Interface allow direct sub selection
183+ (with using a Fragment), while Unions don't.
168184
169- ## 3. A type of an Union is removed.
185+ ### 2D: A Union is replaced with an Object or Interface
186+
187+ ### 2E: An Object is replaced with an Interface
188+
189+ ### 2F: An Interface is replaced with an Object
190+
191+ ## 3. A member type of a Union is removed
170192
171193Every request which queried the type via Fragment becomes invalid.
172194{{< highlight Scala "linenos=table" >}}
@@ -178,48 +200,79 @@ Every request which queried the type via Fragment becomes invalid.
178200}
179201{{< / highlight >}}
180202
181- ## 4. A value is removed from an Enum which is used as input.
203+ ## 4. A value is removed from an Enum which is used as input
182204
183205Every request which used the value becomes invalid.
184206
185- ## 5. A required input field or argument is added which doesn't have a default value.
207+ ## 5. A required input field or argument is added which doesn't have a default value
186208
187209Every request which queried the field becomes invalid because the required
188210argument or input field is not provided.
189211
190- ## 6. An Interface is removed from an Object or Interface.
212+ ## 6. A field is removed
213+
214+ Every request which queried the failed becomes invalid.
215+
216+ ## 7. The type of a field is changed
217+
218+
219+ ## 8. An Interface is removed from an Object or Interface
191220
192221Every request which queried the type via Fragment becomes invalid.
193222
194- ## 7 . An argument or input field is removed.
223+ ## 9 . An argument or input field is removed
195224
196225Every request which provided the argument or input field becomes invalid.
197226
198- ## 8 . An argument type or input field is changed in an incompatible way.
227+ ## 10 . An argument type or input field is changed in an incompatible way
199228
200229Any change which is not just removing non-nullable constraints is breaking.
201230
202231TODO: more explanation.
203232
204- ## 9 . A Query Directive was removed.
233+ ## 11 . A Query Directive is removed
205234
206235Every request which used the Directive becomes invalid.
207236
208- ## 10 . A Query Directive was changed from repeatable to not repeatable.
237+ ## 12 . A Query Directive is changed from repeatable to not repeatable
209238
210239Every request which provided multiple instances of the Directive on the same element
211240becomes invalid.
212241
213- ## 11 . A Query location for a Query Directive was removed.
242+ ## 13 . A Query location for a Query Directive is removed
214243
215244Every request which has the Directive on the now removed location becomes invalid.
216245
217- ## 12. A value is added to an Enum.
246+ ## 14. A value is added to an Enum
247+
248+ If a client doesn't expect new Enum values it can cause problems.
249+ For example a switch over all Enum values is not able to handle a
250+ new unknown value.
251+
252+ ## 15. A type is added to a Union
253+
254+ If a client doesn't expect that Union members can grow, it can cause problems.
255+
256+ For example a query over all Union members:
257+ {{< highlight Scala "linenos=table" >}}
258+ { unionField {
259+ ... on Member1{
260+ # more
261+ }
262+ ... on Member2{
263+ # more
264+ }
265+ ... on Member3{
266+ # more
267+ }
268+ }
269+ {{< / highlight >}}
218270
219- If a client is not developed in defensive way which expects new Enum values
220- it can cause problems.
271+ When at development time the Union only consist of 3 member types,
272+ but is expanded later the query above will result in empty Objects for these
273+ new types. If a client might not be able to handle that.
221274
222- ## 13. Default value for argument or input field is changed
275+ ## 16. A Default value for argument or input field is changed
223276
224277Every request which didn't provide any value for this argument
225278or input field is now using the new default value.
@@ -239,14 +292,17 @@ As discussed above there are different aspects to a change we should consider:
239292| #3 Union type removed | yes | no | na |
240293| #4 Input Enum value removed | yes | no | na |
241294| #5 Required input added | yes | | |
242- | #6 Interface removed | yes | | |
243- | #7 Argument/Input field removed | yes | | |
244- | #8 Argument/Input field type changed | yes | | |
245- | #9 Query directive removed | yes | | |
246- | #10 Query directive non-repeatable | yes | | |
247- | #11 Query directive location removed | yes | | |
248- | #12 Value added to Enum | no | no | yes |
249- | #13 Default value changed | no | no | yes |
295+ | #6 Required input added | yes | | |
296+ | #7 Required input added | yes | | |
297+ | #8 Interface removed | yes | | |
298+ | #9 Argument/Input field removed | yes | | |
299+ | #10 Argument/Input field type changed | yes | | |
300+ | #11 Query directive removed | yes | | |
301+ | #12 Query directive non-repeatable | yes | | |
302+ | #13 Query directive location removed | yes | | |
303+ | #14 Value added to Enum | no | no | yes |
304+ | #15 Type added to Enum | no | no | yes |
305+ | #16 Default value changed | no | no | yes |
250306
251307
252308# Feedback or questions
0 commit comments