-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Getting Started Documentation — No Binary Approach #416
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
601354b
Add blockquote breakout style
a36fffd
Updated getting started with new no-binary approach
94b95d9
Some CSS fixes
1dfaf63
Minor updates to getting started from feedback
9dba96d
Fix GraphQL capitalisation
3a7a506
Add handler import to root cmd
04a7243
Re-add final touches section to getting started
e236d8f
Remove generate command from resolver.go
b9fbb64
Mention recursive-ness of generate ./...
878f394
Minor fixes to getting started code examples
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
//go:generate gorunpkg github.com/99designs/gqlgen | ||
|
||
package {{ .PackageName }} | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
//go:generate gorunpkg github.com/99designs/gqlgen | ||
|
||
package testserver | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,60 @@ | ||
--- | ||
linkTitle: Getting Started | ||
title: Building graphql servers in golang | ||
description: Get started building type-safe graphql servers in Golang using gqlgen | ||
title: Building GraphQL servers in golang | ||
description: Get started building type-safe GraphQL servers in Golang using gqlgen | ||
menu: main | ||
weight: -5 | ||
--- | ||
|
||
## Goal | ||
This tutorial will take you through the process of building a GraphQL server with gqlgen that can: | ||
|
||
The aim for this tutorial is to build a "todo" graphql server that can: | ||
|
||
- get a list of all todos | ||
- create new todos | ||
- mark off todos as they are completed | ||
- Return a list of todos | ||
- Create new todos | ||
- Mark off todos as they are completed | ||
|
||
You can find the finished code for this tutorial [here](https://github.com/vektah/gqlgen-tutorials/tree/master/gettingstarted) | ||
|
||
## Install gqlgen | ||
|
||
Assuming you already have a working [go environment](https://golang.org/doc/install) you can simply go get: | ||
This article uses [`dep`](https://github.com/golang/dep) to install gqlgen. [Follow the instructions for your environment](https://github.com/golang/dep) to install. | ||
|
||
Assuming you already have a working [Go environment](https://golang.org/doc/install), create a directory for the project in your `$GOPATH`: | ||
|
||
```sh | ||
$ mkdir -p $GOPATH/src/github.com/[username]/gqlgen-todos | ||
``` | ||
|
||
> Go Modules | ||
> | ||
> Currently `gqlgen` does not support Go Modules. This is due to the [`loader`](https://godoc.org/golang.org/x/tools/go/loader) package, that also does not yet support Go Modules. We are looking at solutions to this and the issue is tracked in Github. | ||
|
||
Add the following file to your project under `scripts/gqlgen.go`: | ||
|
||
```go | ||
// +build ignore | ||
vektah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
package main | ||
|
||
import "github.com/99designs/gqlgen/cmd" | ||
|
||
func main() { | ||
cmd.Execute() | ||
} | ||
``` | ||
|
||
Lastly, initialise dep. This will inspect any imports you have in your project, and pull down the latest tagged release. | ||
|
||
```sh | ||
go get -u github.com/99designs/gqlgen github.com/vektah/gorunpkg | ||
$ dep init | ||
``` | ||
|
||
## Building the server | ||
|
||
### Define the schema | ||
|
||
gqlgen is a schema-first library, so before touching any code we write out the API we want using the graphql | ||
[Schema Definition Language](http://graphql.org/learn/schema/). This usually goes into a file called schema.graphql | ||
gqlgen is a schema-first library — before writing code, you describe your API using the GraphQL | ||
[Schema Definition Language](http://graphql.org/learn/schema/). This usually goes into a file called `schema.graphql`: | ||
|
||
`schema.graphql` | ||
```graphql | ||
type Todo { | ||
id: ID! | ||
|
@@ -60,23 +83,29 @@ type Mutation { | |
``` | ||
|
||
### Create the project skeleton | ||
|
||
```bash | ||
$ gqlgen init | ||
Exec "go run ./server/server.go" to start GraphQL server | ||
$ go run scripts/gqlgen.go init | ||
``` | ||
|
||
This has created an empty skeleton with all files we need: | ||
This has created an empty skeleton with all files you need: | ||
|
||
- `gqlgen.yml` — The gqlgen config file, knobs for controlling the generated code. | ||
- `generated.go` — The GraphQL execution runtime, the bulk of the generated code. | ||
- `models_gen.go` — Generated models required to build the graph. Often you will override these with your own models. Still very useful for input types. | ||
- `resolver.go` — This is where your application code lives. `generated.go` will call into this to get the data the user has requested. | ||
vektah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- `server/server.go` — This is a minimal entry point that sets up an `http.Handler` to the generated GraphQL server. | ||
|
||
Now run dep ensure, so that we can ensure that the newly generated code's dependencies are all present: | ||
|
||
- gqlgen.yml - The gqlgen config file, knobs for controlling the generated code. | ||
- generated.go - The graphql execution runtime, the bulk of the generated code | ||
- models_gen.go - Generated models required to build the graph. Often you will override these with models you write yourself. Still very useful for input types. | ||
- resolver.go - This is where your application code lives. generated.go will call into this to get the data the user has requested. | ||
```sh | ||
$ dep ensure | ||
``` | ||
|
||
### Create the database models | ||
|
||
The generated model for Todo isnt quite right, it has a user embeded in it but we only want to fetch it if the user actually requested it. So lets make our own. | ||
The generated model for Todo isn't right, it has a user embeded in it but we only want to fetch it if the user actually requested it. So instead lets make a new model in `todo.go`: | ||
|
||
`todo.go` | ||
```go | ||
package gettingstarted | ||
|
||
|
@@ -88,22 +117,27 @@ type Todo struct { | |
} | ||
``` | ||
|
||
And then tell gqlgen to use this new struct by adding this to the gqlgen.yml: | ||
Next tell gqlgen to use this new struct by adding it to `gqlgen.yml`: | ||
|
||
```yaml | ||
models: | ||
Todo: | ||
model: github.com/vektah/gqlgen-tutorials/gettingstarted.Todo | ||
model: github.com/[username]/gqlgen-todos/gettingstarted.Todo | ||
``` | ||
|
||
and regenerate by running | ||
Regenerate by running: | ||
|
||
```bash | ||
$ gqlgen -v | ||
Unable to bind Todo.user to github.com/vektah/gqlgen-tutorials/gettingstarted.Todo | ||
$ go run scripts/gqlgen.go -v | ||
Unable to bind Todo.user to github.com/[username]/gqlgen-todos/gettingstarted.Todo | ||
no method named user | ||
no field named user | ||
Adding resolver method | ||
``` | ||
*note* we've used the verbose flag here to show what gqlgen is doing. Its looked at all the fields on our model and found matching methods for all of them, except user. For user it added a resolver to the interface we need to implement. This is the magic that makes gqlgen work so well. | ||
|
||
> Note | ||
> | ||
> The verbose flag `-v` is here to show what gqlgen is doing. It has looked at all the fields on the model and found matching methods for all of them, except user. For user it has added a resolver to the interface you need to implement. *This is the magic that makes gqlgen work so well!* | ||
|
||
### Implement the resolvers | ||
|
||
|
@@ -151,18 +185,17 @@ better than generating. | |
|
||
### Write the resolvers | ||
|
||
This is a work in progress, we have a way to generate resolver stubs, but it cannot currently update existing code. We can force it to run again by deleting `resolvers.go` and re-running gqlgen: | ||
This is a work in progress, we have a way to generate resolver stubs, but it cannot currently update existing code. We can force it to run again by deleting `resolver.go` and re-running gqlgen: | ||
|
||
```bash | ||
rm resolvers.go | ||
gqlgen | ||
$ rm resolver.go | ||
$ go run scripts/gqlgen.go | ||
``` | ||
|
||
Now we just need to fill in the `not implemented` parts | ||
|
||
Now we just need to fill in the `not implemented` parts. Update `graph/graph.go` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think (for me) this should be "Update |
||
|
||
`graph/graph.go` | ||
```go | ||
//go:generate gorunpkg github.com/99designs/gqlgen | ||
//go:generate go run ./scripts/gqlgen.go | ||
|
||
package gettingstarted | ||
|
||
|
@@ -242,34 +275,14 @@ query findTodos { | |
|
||
## Finishing touches | ||
|
||
gqlgen is still unstable, and the APIs may change at any time. To prevent changes from ruining your day make sure | ||
to lock your dependencies: | ||
|
||
*Note*: If you dont have dep installed yet, you can get it [here](https://github.com/golang/dep) | ||
|
||
First uninstall the global version we grabbed earlier. This is a good way to prevent version mismatch footguns. | ||
|
||
```bash | ||
rm ~/go/bin/gqlgen | ||
rm -rf ~/go/src/github.com/99designs/gqlgen | ||
``` | ||
At the top of our `resolver.go` add the following line: | ||
|
||
Next install gorunpkg, its kind of like npx but only searches vendor. | ||
|
||
```bash | ||
dep init | ||
dep ensure | ||
``` | ||
|
||
At the top of our resolvers.go a go generate command was added that looks like this: | ||
```go | ||
//go:generate gorunpkg github.com/99designs/gqlgen | ||
//go:generate go run scripts/gqlgen.go -v | ||
``` | ||
|
||
This magic comment tells `go generate` what command to run when we want to regenerate our code. to do so run: | ||
This magic comment tells `go generate` what command to run when we want to regenerate our code. To run go generate recursively over your entire project, use this command: | ||
|
||
```go | ||
go generate ./... | ||
``` | ||
|
||
*gorunpkg* will build and run the version of gqlgen we just installed into vendor with dep. This makes sure that everyone working on your project generates code the same way regardless which binaries are installed in their gopath. | ||
|
||
``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be enough to get
init
to run cleanly. Attempting to runserver/server.go
afterwards however still requires some additional deps (websockets I think). So I added adep ensure
aftergqlgen init
in the docs.