diff --git a/README.md b/README.md index 0f3cfeb..fc1a4b8 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,13 @@ Exec "go run ./server.go" to start GraphQL server $ go run server.go 2021/03/02 16:29:48 connect to http://localhost:8080/ for GraphQL playground ``` + +## Step 2. Add code slightly more realistic + +Add new `graph/model/todo.go`, regenerate the code and implement the new resolver into `graph/schema.resolvers.go`. + +```bash +$ go generate +$ go run server.go +2021/03/02 20:35:39 connect to http://localhost:8080/ for GraphQL playground +``` diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 3e77198..647a2d3 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -37,6 +37,7 @@ type Config struct { type ResolverRoot interface { Mutation() MutationResolver Query() QueryResolver + Todo() TodoResolver } type DirectiveRoot struct { @@ -70,6 +71,9 @@ type MutationResolver interface { type QueryResolver interface { Todos(ctx context.Context) ([]*model.Todo, error) } +type TodoResolver interface { + User(ctx context.Context, obj *model.Todo) (*model.User, error) +} type executableSchema struct { resolvers ResolverRoot @@ -578,14 +582,14 @@ func (ec *executionContext) _Todo_user(ctx context.Context, field graphql.Collec Object: "Todo", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.User, nil + return ec.resolvers.Todo().User(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -1884,23 +1888,32 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj case "id": out.Values[i] = ec._Todo_id(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "text": out.Values[i] = ec._Todo_text(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "done": out.Values[i] = ec._Todo_done(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "user": - out.Values[i] = ec._Todo_user(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Todo_user(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -2290,6 +2303,10 @@ func (ec *executionContext) marshalNTodo2ᚖgithubᚗcomᚋeisenheimjelidᚋlear return ec._Todo(ctx, sel, v) } +func (ec *executionContext) marshalNUser2githubᚗcomᚋeisenheimjelidᚋlearnᚑgqlgenᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v model.User) graphql.Marshaler { + return ec._User(ctx, sel, &v) +} + func (ec *executionContext) marshalNUser2ᚖgithubᚗcomᚋeisenheimjelidᚋlearnᚑgqlgenᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v *model.User) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 70ebe4f..bd3d473 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -7,13 +7,6 @@ type NewTodo struct { UserID string `json:"userId"` } -type Todo struct { - ID string `json:"id"` - Text string `json:"text"` - Done bool `json:"done"` - User *User `json:"user"` -} - type User struct { ID string `json:"id"` Name string `json:"name"` diff --git a/graph/model/todo.go b/graph/model/todo.go new file mode 100644 index 0000000..954762f --- /dev/null +++ b/graph/model/todo.go @@ -0,0 +1,8 @@ +package model + +type Todo struct { + ID string `json:"id"` + Text string `json:"text"` + Done bool `json:"done"` + UserID string `json:"user"` +} diff --git a/graph/resolver.go b/graph/resolver.go index e312921..a5d1a04 100644 --- a/graph/resolver.go +++ b/graph/resolver.go @@ -1,5 +1,6 @@ package graph +//go:generate go run github.com/99designs/gqlgen import "github.com/eisenheimjelid/learn-gqlgen/graph/model" // This file will not be regenerated automatically. diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index 957d8a8..5f17b13 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -14,9 +14,9 @@ import ( func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { todo := &model.Todo{ - Text: input.Text, - ID: fmt.Sprintf("T%d", rand.Intn(100)), - User: &model.User{ID: input.UserID, Name: "user " + input.UserID}, + Text: input.Text, + ID: fmt.Sprintf("T%d", rand.Intn(100)), + UserID: input.UserID, // fix this line } r.todos = append(r.todos, todo) return todo, nil @@ -26,11 +26,19 @@ func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) { return r.todos, nil } +func (r *todoResolver) User(ctx context.Context, obj *model.Todo) (*model.User, error) { + return &model.User{ID: obj.UserID, Name: "user " + obj.UserID}, nil +} + // Mutation returns generated.MutationResolver implementation. func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} } // Query returns generated.QueryResolver implementation. func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } +// Todo returns generated.TodoResolver implementation. +func (r *Resolver) Todo() generated.TodoResolver { return &todoResolver{r} } + type mutationResolver struct{ *Resolver } type queryResolver struct{ *Resolver } +type todoResolver struct{ *Resolver }