From 6d13b37830a67981d41a4099f3ade3ce5f5bbb51 Mon Sep 17 00:00:00 2001 From: talksik Date: Tue, 23 May 2023 17:06:07 -0700 Subject: [PATCH] adding in new fields with user todos and query --- graph/generated.go | 191 +++++++++++++++++++++++++++++++++++++- graph/model/models_gen.go | 5 +- graph/resolver.go | 24 +---- graph/schema.graphqls | 2 + graph/schema.resolvers.go | 63 ++++++++++++- 5 files changed, 257 insertions(+), 28 deletions(-) diff --git a/graph/generated.go b/graph/generated.go index 2fe1e7a..3cc01c9 100644 --- a/graph/generated.go +++ b/graph/generated.go @@ -51,6 +51,7 @@ type ComplexityRoot struct { Query struct { Todos func(childComplexity int) int + User func(childComplexity int, id string) int } Todo struct { @@ -61,8 +62,9 @@ type ComplexityRoot struct { } User struct { - ID func(childComplexity int) int - Name func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + Todos func(childComplexity int) int } } @@ -71,6 +73,7 @@ type MutationResolver interface { } type QueryResolver interface { Todos(ctx context.Context) ([]*model.Todo, error) + User(ctx context.Context, id string) (*model.User, error) } type executableSchema struct { @@ -107,6 +110,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Todos(childComplexity), true + case "Query.user": + if e.complexity.Query.User == nil { + break + } + + args, err := ec.field_Query_user_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.User(childComplexity, args["id"].(string)), true + case "Todo.done": if e.complexity.Todo.Done == nil { break @@ -149,6 +164,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.User.Name(childComplexity), true + case "User.todos": + if e.complexity.User.Todos == nil { + break + } + + return e.complexity.User.Todos(childComplexity), true + } return 0, false } @@ -267,6 +289,21 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs return args, nil } +func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -424,6 +461,66 @@ func (ec *executionContext) fieldContext_Query_todos(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_user(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().User(rctx, fc.Args["id"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.User) + fc.Result = res + return ec.marshalOUser2ᚖgithubᚗcomᚋtalksikᚋgraphqlᚑgolangᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_user(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_User_id(ctx, field) + case "name": + return ec.fieldContext_User_name(ctx, field) + case "todos": + return ec.fieldContext_User_todos(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type User", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_user_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query___type(ctx, field) if err != nil { @@ -728,6 +825,8 @@ func (ec *executionContext) fieldContext_Todo_user(ctx context.Context, field gr return ec.fieldContext_User_id(ctx, field) case "name": return ec.fieldContext_User_name(ctx, field) + case "todos": + return ec.fieldContext_User_todos(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) }, @@ -823,6 +922,60 @@ func (ec *executionContext) fieldContext_User_name(ctx context.Context, field gr return fc, nil } +func (ec *executionContext) _User_todos(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_User_todos(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Todos, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.Todo) + fc.Result = res + return ec.marshalNTodo2ᚕᚖgithubᚗcomᚋtalksikᚋgraphqlᚑgolangᚋgraphᚋmodelᚐTodoᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_User_todos(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "User", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Todo_id(ctx, field) + case "text": + return ec.fieldContext_Todo_text(ctx, field) + case "done": + return ec.fieldContext_Todo_done(ctx, field) + case "user": + return ec.fieldContext_Todo_user(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Todo", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { fc, err := ec.fieldContext___Directive_name(ctx, field) if err != nil { @@ -2720,6 +2873,26 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) } + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + case "user": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_user(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + out.Concurrently(i, func() graphql.Marshaler { return rrm(innerCtx) }) @@ -2816,6 +2989,13 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj out.Values[i] = ec._User_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "todos": + + out.Values[i] = ec._User_todos(ctx, field, obj) + if out.Values[i] == graphql.Null { invalids++ } @@ -3561,6 +3741,13 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as return res } +func (ec *executionContext) marshalOUser2ᚖgithubᚗcomᚋtalksikᚋgraphqlᚑgolangᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v *model.User) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._User(ctx, sel, v) +} + func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 70ebe4f..0b88d1c 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -15,6 +15,7 @@ type Todo struct { } type User struct { - ID string `json:"id"` - Name string `json:"name"` + ID string `json:"id"` + Name string `json:"name"` + Todos []*Todo `json:"todos"` } diff --git a/graph/resolver.go b/graph/resolver.go index 7b1191e..a166eb5 100644 --- a/graph/resolver.go +++ b/graph/resolver.go @@ -1,3 +1,5 @@ +//go:generate go run github.com/99designs/gqlgen generate + package graph import "github.com/talksik/graphql-golang/graph/model" @@ -7,28 +9,6 @@ import "github.com/talksik/graphql-golang/graph/model" // It serves as dependency injection for your app, add any dependencies you require here. -var todos = []*model.Todo{ - { - ID: "1", - Text: "laundry", - Done: false, - }, - { - ID: "2", - Text: "woah", - Done: false, - }, - { - ID: "3", - Text: "Hello", - Done: false, - User: &model.User{ - ID: "1", - Name: "Talksik", - }, - }, -} - type Resolver struct{ Todos []*model.Todo } diff --git a/graph/schema.graphqls b/graph/schema.graphqls index c6a91bb..a0941e2 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -12,10 +12,12 @@ type Todo { type User { id: ID! name: String! + todos: [Todo!]! } type Query { todos: [Todo!]! + user(id: ID!): User } input NewTodo { diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index 167e944..a2c030a 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -11,22 +11,81 @@ import ( "github.com/talksik/graphql-golang/graph/model" ) +// !!! WARNING !!! +// The code below was going to be deleted when updating resolvers. It has been copied here so you have +// one last chance to move it out of harms way if you want. There are two reasons this happens: +// - When renaming or deleting a resolver the old code will be put in here. You can safely delete +// it when you're done. +// - You have helper methods in this file. Move them out to keep these resolver files clean. +var todos = []*model.Todo{ + { + ID: "1", + Text: "laundry", + Done: false, + User: &model.User{ + ID: "1", + Name: "Talksik", + }, + }, + { + ID: "2", + Text: "woah", + Done: false, + User: &model.User{ + ID: "1", + Name: "Talksik", + }, + }, + { + ID: "3", + Text: "Hello", + Done: false, + User: &model.User{ + ID: "1", + Name: "Talksik", + }, + }, +} + // CreateTodo is the resolver for the createTodo field. func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { newTodo := &model.Todo{ ID: fmt.Sprintf("T%d", len(r.Todos)+1), Text: input.Text, Done: false, + User: &model.User{ + ID: input.Text, + Name: "Talksik", + }, } - r.Resolver.Todos = append(r.Resolver.Todos, newTodo) + todos = append(todos, newTodo) return newTodo, nil } // Todos is the resolver for the todos field. func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) { - return r.Resolver.Todos, nil + return todos, nil +} + +// User is the resolver for the user field. +func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) { + // get the user + user := &model.User{ + ID: "1", + Name: "Talksik", + Todos: []*model.Todo{}, + } + + // get the todos for the user + for _, todo := range todos { + if todo.User.ID == user.ID { + user.Todos = append(user.Todos, todo) + } + } + + return user, nil } // Mutation returns MutationResolver implementation.