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