1graphql
2=======
3
4[](https://travis-ci.org/shurcooL/graphql) [](https://godoc.org/github.com/shurcooL/graphql)
5
6Package `graphql` provides a GraphQL client implementation.
7
8For more information, see package [`github.com/shurcooL/githubv4`](https://github.com/shurcooL/githubv4), which is a specialized version targeting GitHub GraphQL API v4. That package is driving the feature development.
9
10Installation
11------------
12
13`graphql` requires Go version 1.8 or later.
14
15```bash
16go get -u github.com/shurcooL/graphql
17```
18
19Usage
20-----
21
22Construct a GraphQL client, specifying the GraphQL server URL. Then, you can use it to make GraphQL queries and mutations.
23
24```Go
25client := graphql.NewClient("https://example.com/graphql", nil)
26// Use client...
27```
28
29### Authentication
30
31Some GraphQL servers may require authentication. The `graphql` package does not directly handle authentication. Instead, when creating a new client, you're expected to pass an `http.Client` that performs authentication. The easiest and recommended way to do this is to use the [`golang.org/x/oauth2`](https://golang.org/x/oauth2) package. You'll need an OAuth token with the right scopes. Then:
32
33```Go
34import "golang.org/x/oauth2"
35
36func main() {
37 src := oauth2.StaticTokenSource(
38 &oauth2.Token{AccessToken: os.Getenv("GRAPHQL_TOKEN")},
39 )
40 httpClient := oauth2.NewClient(context.Background(), src)
41
42 client := graphql.NewClient("https://example.com/graphql", httpClient)
43 // Use client...
44```
45
46### Simple Query
47
48To make a GraphQL query, you need to define a corresponding Go type.
49
50For example, to make the following GraphQL query:
51
52```GraphQL
53query {
54 me {
55 name
56 }
57}
58```
59
60You can define this variable:
61
62```Go
63var query struct {
64 Me struct {
65 Name graphql.String
66 }
67}
68```
69
70Then call `client.Query`, passing a pointer to it:
71
72```Go
73err := client.Query(context.Background(), &query, nil)
74if err != nil {
75 // Handle error.
76}
77fmt.Println(query.Me.Name)
78
79// Output: Luke Skywalker
80```
81
82### Arguments and Variables
83
84Often, you'll want to specify arguments on some fields. You can use the `graphql` struct field tag for this.
85
86For example, to make the following GraphQL query:
87
88```GraphQL
89{
90 human(id: "1000") {
91 name
92 height(unit: METER)
93 }
94}
95```
96
97You can define this variable:
98
99```Go
100var q struct {
101 Human struct {
102 Name graphql.String
103 Height graphql.Float `graphql:"height(unit: METER)"`
104 } `graphql:"human(id: \"1000\")"`
105}
106```
107
108Then call `client.Query`:
109
110```Go
111err := client.Query(context.Background(), &q, nil)
112if err != nil {
113 // Handle error.
114}
115fmt.Println(q.Human.Name)
116fmt.Println(q.Human.Height)
117
118// Output:
119// Luke Skywalker
120// 1.72
121```
122
123However, that'll only work if the arguments are constant and known in advance. Otherwise, you will need to make use of variables. Replace the constants in the struct field tag with variable names:
124
125```Go
126var q struct {
127 Human struct {
128 Name graphql.String
129 Height graphql.Float `graphql:"height(unit: $unit)"`
130 } `graphql:"human(id: $id)"`
131}
132```
133
134Then, define a `variables` map with their values:
135
136```Go
137variables := map[string]interface{}{
138 "id": graphql.ID(id),
139 "unit": starwars.LengthUnit("METER"),
140}
141```
142
143Finally, call `client.Query` providing `variables`:
144
145```Go
146err := client.Query(context.Background(), &q, variables)
147if err != nil {
148 // Handle error.
149}
150```
151
152### Inline Fragments
153
154Some GraphQL queries contain inline fragments. You can use the `graphql` struct field tag to express them.
155
156For example, to make the following GraphQL query:
157
158```GraphQL
159{
160 hero(episode: "JEDI") {
161 name
162 ... on Droid {
163 primaryFunction
164 }
165 ... on Human {
166 height
167 }
168 }
169}
170```
171
172You can define this variable:
173
174```Go
175var q struct {
176 Hero struct {
177 Name graphql.String
178 Droid struct {
179 PrimaryFunction graphql.String
180 } `graphql:"... on Droid"`
181 Human struct {
182 Height graphql.Float
183 } `graphql:"... on Human"`
184 } `graphql:"hero(episode: \"JEDI\")"`
185}
186```
187
188Alternatively, you can define the struct types corresponding to inline fragments, and use them as embedded fields in your query:
189
190```Go
191type (
192 DroidFragment struct {
193 PrimaryFunction graphql.String
194 }
195 HumanFragment struct {
196 Height graphql.Float
197 }
198)
199
200var q struct {
201 Hero struct {
202 Name graphql.String
203 DroidFragment `graphql:"... on Droid"`
204 HumanFragment `graphql:"... on Human"`
205 } `graphql:"hero(episode: \"JEDI\")"`
206}
207```
208
209Then call `client.Query`:
210
211```Go
212err := client.Query(context.Background(), &q, nil)
213if err != nil {
214 // Handle error.
215}
216fmt.Println(q.Hero.Name)
217fmt.Println(q.Hero.PrimaryFunction)
218fmt.Println(q.Hero.Height)
219
220// Output:
221// R2-D2
222// Astromech
223// 0
224```
225
226### Mutations
227
228Mutations often require information that you can only find out by performing a query first. Let's suppose you've already done that.
229
230For example, to make the following GraphQL mutation:
231
232```GraphQL
233mutation($ep: Episode!, $review: ReviewInput!) {
234 createReview(episode: $ep, review: $review) {
235 stars
236 commentary
237 }
238}
239variables {
240 "ep": "JEDI",
241 "review": {
242 "stars": 5,
243 "commentary": "This is a great movie!"
244 }
245}
246```
247
248You can define:
249
250```Go
251var m struct {
252 CreateReview struct {
253 Stars graphql.Int
254 Commentary graphql.String
255 } `graphql:"createReview(episode: $ep, review: $review)"`
256}
257variables := map[string]interface{}{
258 "ep": starwars.Episode("JEDI"),
259 "review": starwars.ReviewInput{
260 Stars: graphql.Int(5),
261 Commentary: graphql.String("This is a great movie!"),
262 },
263}
264```
265
266Then call `client.Mutate`:
267
268```Go
269err := client.Mutate(context.Background(), &m, variables)
270if err != nil {
271 // Handle error.
272}
273fmt.Printf("Created a %v star review: %v\n", m.CreateReview.Stars, m.CreateReview.Commentary)
274
275// Output:
276// Created a 5 star review: This is a great movie!
277```
278
279Directories
280-----------
281
282| Path | Synopsis |
283|----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
284| [example/graphqldev](https://godoc.org/github.com/shurcooL/graphql/example/graphqldev) | graphqldev is a test program currently being used for developing graphql package. |
285| [ident](https://godoc.org/github.com/shurcooL/graphql/ident) | Package ident provides functions for parsing and converting identifier names between various naming convention. |
286| [internal/jsonutil](https://godoc.org/github.com/shurcooL/graphql/internal/jsonutil) | Package jsonutil provides a function for decoding JSON into a GraphQL query data structure. |
287
288License
289-------
290
291- [MIT License](LICENSE)
View as plain text