Skip to content

Commit 460caae

Browse files
committed
Initial stab at validation learn page
1 parent 080a779 commit 460caae

File tree

5 files changed

+175
-16
lines changed

5 files changed

+175
-16
lines changed

site/docs/validation/index.html

Lines changed: 0 additions & 14 deletions
This file was deleted.

site/docs/validation/index.html.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var React = require('react')
2+
var Redirect = require('../../_core/Redirect')
3+
export default () => <Redirect to="/learn/validation/" />

site/docs/videos/index.html.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
var React = require('react')
2-
var Redirect = require('../_core/Redirect')
2+
var Redirect = require('../../_core/Redirect')
33
export default () => <Redirect to="/community/#videos" />

site/learn/Learn-Schema.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Schemas and Types
33
layout: ../_core/DocsLayout
44
category: Learn
55
permalink: /learn/schema/
6-
next: /learn/thinking-in-graphs/
6+
next: /learn/validation/
77
sublinks: type-system,type-language,object-types-and-fields,arguments,the-query-and-mutation-types,scalar-types,enumeration-types,lists-and-non-null,interfaces,union-types,input-types
88
---
99

site/learn/Learn-Validation.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
---
2+
title: Validation
3+
layout: ../_core/DocsLayout
4+
category: Learn
5+
permalink: /learn/validation/
6+
next: /learn/thinking-in-graphs/
7+
---
8+
9+
By using the type system, it can be predetermined whether a GraphQL query
10+
is valid or not. This allows servers and clients to effectively inform
11+
developers when an invalid query has been created, without having to rely
12+
on runtime checks.
13+
14+
For our Star Wars example, the file
15+
[starWarsValidation-test.js](https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsValidation-test.js)
16+
contains a number of queries demonstrating various invalidities, and is a test
17+
file that can be run to exercise the reference implementation's validator.
18+
19+
To start, let's take a complex valid query. This is a nested query, similar to
20+
an example from the previous section, but with the duplicated fields factored
21+
out into a fragment:
22+
23+
```graphql
24+
# { "graphiql": true }
25+
{
26+
hero {
27+
...NameAndAppearances
28+
friends {
29+
...NameAndAppearances
30+
friends {
31+
...NameAndAppearances
32+
}
33+
}
34+
}
35+
}
36+
37+
fragment NameAndAppearances on Character {
38+
name
39+
appearsIn
40+
}
41+
```
42+
43+
And this query is valid. Let's take a look at some invalid queries...
44+
45+
A fragment cannot refer to itself or create a cycle, as this could result in
46+
an unbounded result! Here's the same query above but without the explicit three
47+
levels of nesting:
48+
49+
```graphql
50+
# { "graphiql": true }
51+
{
52+
hero {
53+
...NameAndAppearancesAndFriends
54+
}
55+
}
56+
57+
fragment NameAndAppearancesAndFriends on Character {
58+
name
59+
appearsIn
60+
friends {
61+
...NameAndAppearancesAndFriends
62+
}
63+
}
64+
```
65+
66+
When we query for fields, we have to query for a field that exists on the
67+
given type. So as `hero` returns a `Character`, we have to query for a field
68+
on `Character`. That type does not have a `favoriteSpaceship` field, so this
69+
query is invalid:
70+
71+
```graphql
72+
# { "graphiql": true }
73+
# INVALID: favoriteSpaceship does not exist on Character
74+
{
75+
hero {
76+
favoriteSpaceship
77+
}
78+
}
79+
```
80+
81+
Whenever we query for a field and it returns something other than a scalar
82+
or an enum, we need to specify what data we want to get back from the field.
83+
Hero returns a `Character`, and we've been requesting fields like `name` and
84+
`appearsIn` on it; if we omit that, the query will not be valid:
85+
86+
```graphql
87+
# { "graphiql": true }
88+
# INVALID: hero is not a scalar, so fields are needed
89+
{
90+
hero
91+
}
92+
```
93+
94+
Similarly, if a field is a scalar, it doesn't make sense to query for
95+
additional fields on it, and doing so will make the query invalid:
96+
97+
```graphql
98+
# { "graphiql": true }
99+
# INVALID: name is a scalar, so fields are not permitted
100+
{
101+
hero {
102+
name {
103+
firstCharacterOfName
104+
}
105+
}
106+
}
107+
```
108+
109+
Earlier, it was noted that a query can only query for fields on the type
110+
in question; when we query for `hero` which returns a `Character`, we
111+
can only query for fields that exist on `Character`. What happens if we
112+
want to query for R2-D2s primary function, though?
113+
114+
```graphql
115+
# { "graphiql": true }
116+
# INVALID: primaryFunction does not exist on Character
117+
{
118+
hero {
119+
name
120+
primaryFunction
121+
}
122+
}
123+
```
124+
125+
That query is invalid, because `primaryFunction` is not a field on `Character`.
126+
We want some way of indicating that we wish to fetch `primaryFunction` if the
127+
`Character` is a `Droid`, and to ignore that field otherwise. We can use
128+
the fragments we introduced earlier to do this. By setting up a fragment defined
129+
on `Droid` and including it, we ensure that we only query for `primaryFunction`
130+
where it is defined.
131+
132+
```graphql
133+
# { "graphiql": true }
134+
{
135+
hero {
136+
name
137+
...DroidFields
138+
}
139+
}
140+
141+
fragment DroidFields on Droid {
142+
primaryFunction
143+
}
144+
```
145+
146+
This query is valid, but it's a bit verbose; named fragments were valuable
147+
above when we used them multiple times, but we're only using this one once.
148+
Instead of using a named fragment, we can use an inline fragment; this
149+
still allows us to indicate the type we are querying on, but without naming
150+
a separate fragment:
151+
152+
```graphql
153+
# { "graphiql": true }
154+
{
155+
hero {
156+
name
157+
... on Droid {
158+
primaryFunction
159+
}
160+
}
161+
}
162+
```
163+
164+
This has just scratched the surface of the validation system; there
165+
are a number of validation rules in place to ensure that a GraphQL query
166+
is semantically meaningful. The specification goes into more detail about this
167+
topic in the "Validation" section, and the
168+
[validation](https://github.com/graphql/graphql-js/blob/master/src/validation)
169+
directory in GraphQL.js contains code implementing a
170+
specification-compliant GraphQL validator.

0 commit comments

Comments
 (0)