github.com/jepp2078/gqlgen@v0.7.2/example/todo/todo.go (about) 1 //go:generate gorunpkg github.com/99designs/gqlgen 2 3 package todo 4 5 import ( 6 "context" 7 "errors" 8 "fmt" 9 "time" 10 11 "github.com/99designs/gqlgen/graphql" 12 "github.com/mitchellh/mapstructure" 13 ) 14 15 var you = &User{ID: 1, Name: "You"} 16 var them = &User{ID: 2, Name: "Them"} 17 18 func New() Config { 19 c := Config{ 20 Resolvers: &resolvers{ 21 todos: []Todo{ 22 {ID: 1, Text: "A todo not to forget", Done: false, owner: you}, 23 {ID: 2, Text: "This is the most important", Done: false, owner: you}, 24 {ID: 3, Text: "Somebody else's todo", Done: true, owner: them}, 25 {ID: 4, Text: "Please do this or else", Done: false, owner: you}, 26 }, 27 lastID: 4, 28 }, 29 } 30 c.Directives.HasRole = func(ctx context.Context, obj interface{}, next graphql.Resolver, role Role) (interface{}, error) { 31 switch role { 32 case RoleAdmin: 33 // No admin for you! 34 return nil, nil 35 case RoleOwner: 36 // This is also available in context 37 if obj != graphql.GetResolverContext(ctx).Parent.Result { 38 return nil, fmt.Errorf("parent type mismatch") 39 } 40 ownable, isOwnable := obj.(Ownable) 41 if !isOwnable { 42 return nil, fmt.Errorf("obj cant be owned") 43 } 44 45 if ownable.Owner().ID != you.ID { 46 return nil, fmt.Errorf("you dont own that") 47 } 48 } 49 50 return next(ctx) 51 } 52 return c 53 } 54 55 type resolvers struct { 56 todos []Todo 57 lastID int 58 } 59 60 func (r *resolvers) MyQuery() MyQueryResolver { 61 return (*QueryResolver)(r) 62 } 63 64 func (r *resolvers) MyMutation() MyMutationResolver { 65 return (*MutationResolver)(r) 66 } 67 68 type QueryResolver resolvers 69 70 func (r *QueryResolver) Todo(ctx context.Context, id int) (*Todo, error) { 71 time.Sleep(220 * time.Millisecond) 72 73 if id == 666 { 74 panic("critical failure") 75 } 76 77 for _, todo := range r.todos { 78 if todo.ID == id { 79 return &todo, nil 80 } 81 } 82 return nil, errors.New("not found") 83 } 84 85 func (r *QueryResolver) LastTodo(ctx context.Context) (*Todo, error) { 86 if len(r.todos) == 0 { 87 return nil, errors.New("not found") 88 } 89 return &r.todos[len(r.todos)-1], nil 90 } 91 92 func (r *QueryResolver) Todos(ctx context.Context) ([]Todo, error) { 93 return r.todos, nil 94 } 95 96 type MutationResolver resolvers 97 98 func (r *MutationResolver) CreateTodo(ctx context.Context, todo TodoInput) (Todo, error) { 99 newID := r.id() 100 101 newTodo := Todo{ 102 ID: newID, 103 Text: todo.Text, 104 owner: you, 105 } 106 107 if todo.Done != nil { 108 newTodo.Done = *todo.Done 109 } 110 111 r.todos = append(r.todos, newTodo) 112 113 return newTodo, nil 114 } 115 116 func (r *MutationResolver) UpdateTodo(ctx context.Context, id int, changes map[string]interface{}) (*Todo, error) { 117 var affectedTodo *Todo 118 119 for i := 0; i < len(r.todos); i++ { 120 if r.todos[i].ID == id { 121 affectedTodo = &r.todos[i] 122 break 123 } 124 } 125 126 if affectedTodo == nil { 127 return nil, nil 128 } 129 130 err := mapstructure.Decode(changes, affectedTodo) 131 if err != nil { 132 panic(err) 133 } 134 135 return affectedTodo, nil 136 } 137 138 func (r *MutationResolver) id() int { 139 r.lastID++ 140 return r.lastID 141 }