README.md

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