Skip to content
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 10 commits into from
Nov 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/internal/gopath"
"github.com/urfave/cli"

// Required since otherwise dep will prune away these unused packages before codegen has a chance to run
_ "github.com/99designs/gqlgen/handler"
Copy link
Contributor Author

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 run server/server.go afterwards however still requires some additional deps (websockets I think). So I added a dep ensure after gqlgen init in the docs.

)

func Execute() {
Expand Down
2 changes: 1 addition & 1 deletion codegen/templates/data.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions codegen/templates/resolver.gotpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//go:generate gorunpkg github.com/99designs/gqlgen

package {{ .PackageName }}

import (
Expand Down
2 changes: 0 additions & 2 deletions codegen/testserver/resolver.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//go:generate gorunpkg github.com/99designs/gqlgen

package testserver

import (
Expand Down
133 changes: 73 additions & 60 deletions docs/content/getting-started.md
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!
Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think (for me) this should be "Update resolver.go"


`graph/graph.go`
```go
//go:generate gorunpkg github.com/99designs/gqlgen
//go:generate go run ./scripts/gqlgen.go

package gettingstarted

Expand Down Expand Up @@ -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.

```
Loading