github.com/Kartograf/gqlgen@v0.7.2/example/starwars/resolvers.go (about) 1 //go:generate gorunpkg github.com/99designs/gqlgen 2 3 package starwars 4 5 import ( 6 "context" 7 "errors" 8 "strings" 9 "time" 10 ) 11 12 type Resolver struct { 13 humans map[string]Human 14 droid map[string]Droid 15 starships map[string]Starship 16 reviews map[Episode][]Review 17 } 18 19 func (r *Resolver) Droid() DroidResolver { 20 return &droidResolver{r} 21 } 22 23 func (r *Resolver) FriendsConnection() FriendsConnectionResolver { 24 return &friendsConnectionResolver{r} 25 } 26 27 func (r *Resolver) Human() HumanResolver { 28 return &humanResolver{r} 29 } 30 31 func (r *Resolver) Mutation() MutationResolver { 32 return &mutationResolver{r} 33 } 34 35 func (r *Resolver) Query() QueryResolver { 36 return &queryResolver{r} 37 } 38 39 func (r *Resolver) Starship() StarshipResolver { 40 return &starshipResolver{r} 41 } 42 43 func (r *Resolver) resolveCharacters(ctx context.Context, ids []string) ([]Character, error) { 44 var result []Character 45 for _, id := range ids { 46 char, err := r.Query().Character(ctx, id) 47 if err != nil { 48 return nil, err 49 } 50 result = append(result, char) 51 } 52 return result, nil 53 } 54 55 type droidResolver struct{ *Resolver } 56 57 func (r *droidResolver) Friends(ctx context.Context, obj *Droid) ([]Character, error) { 58 return r.resolveCharacters(ctx, obj.FriendIds) 59 } 60 61 func (r *droidResolver) FriendsConnection(ctx context.Context, obj *Droid, first *int, after *string) (FriendsConnection, error) { 62 return r.resolveFriendConnection(ctx, obj.FriendIds, first, after) 63 } 64 65 type friendsConnectionResolver struct{ *Resolver } 66 67 func (r *friendsConnectionResolver) Edges(ctx context.Context, obj *FriendsConnection) ([]FriendsEdge, error) { 68 friends, err := r.resolveCharacters(ctx, obj.ids) 69 if err != nil { 70 return nil, err 71 } 72 73 edges := make([]FriendsEdge, obj.to-obj.from) 74 for i := range edges { 75 edges[i] = FriendsEdge{ 76 Cursor: encodeCursor(obj.from + i), 77 Node: friends[obj.from+i], 78 } 79 } 80 return edges, nil 81 } 82 83 func (r *friendsConnectionResolver) Friends(ctx context.Context, obj *FriendsConnection) ([]Character, error) { 84 return r.resolveCharacters(ctx, obj.ids) 85 } 86 87 type humanResolver struct{ *Resolver } 88 89 func (r *humanResolver) Friends(ctx context.Context, obj *Human) ([]Character, error) { 90 return r.resolveCharacters(ctx, obj.FriendIds) 91 } 92 93 func (r *humanResolver) FriendsConnection(ctx context.Context, obj *Human, first *int, after *string) (FriendsConnection, error) { 94 return r.resolveFriendConnection(ctx, obj.FriendIds, first, after) 95 } 96 97 func (r *humanResolver) Starships(ctx context.Context, obj *Human) ([]Starship, error) { 98 var result []Starship 99 for _, id := range obj.StarshipIds { 100 char, err := r.Query().Starship(ctx, id) 101 if err != nil { 102 return nil, err 103 } 104 if char != nil { 105 result = append(result, *char) 106 } 107 } 108 return result, nil 109 } 110 111 type mutationResolver struct{ *Resolver } 112 113 func (r *mutationResolver) CreateReview(ctx context.Context, episode Episode, review Review) (*Review, error) { 114 review.Time = time.Now() 115 time.Sleep(1 * time.Second) 116 r.reviews[episode] = append(r.reviews[episode], review) 117 return &review, nil 118 } 119 120 type queryResolver struct{ *Resolver } 121 122 func (r *queryResolver) Hero(ctx context.Context, episode *Episode) (Character, error) { 123 if *episode == EpisodeEmpire { 124 return r.humans["1000"], nil 125 } 126 return r.droid["2001"], nil 127 } 128 129 func (r *queryResolver) Reviews(ctx context.Context, episode Episode, since *time.Time) ([]Review, error) { 130 if since == nil { 131 return r.reviews[episode], nil 132 } 133 134 var filtered []Review 135 for _, rev := range r.reviews[episode] { 136 if rev.Time.After(*since) { 137 filtered = append(filtered, rev) 138 } 139 } 140 return filtered, nil 141 } 142 143 func (r *queryResolver) Search(ctx context.Context, text string) ([]SearchResult, error) { 144 var l []SearchResult 145 for _, h := range r.humans { 146 if strings.Contains(h.Name, text) { 147 l = append(l, h) 148 } 149 } 150 for _, d := range r.droid { 151 if strings.Contains(d.Name, text) { 152 l = append(l, d) 153 } 154 } 155 for _, s := range r.starships { 156 if strings.Contains(s.Name, text) { 157 l = append(l, s) 158 } 159 } 160 return l, nil 161 } 162 163 func (r *queryResolver) Character(ctx context.Context, id string) (Character, error) { 164 if h, ok := r.humans[id]; ok { 165 return &h, nil 166 } 167 if d, ok := r.droid[id]; ok { 168 return &d, nil 169 } 170 return nil, nil 171 } 172 173 func (r *queryResolver) Droid(ctx context.Context, id string) (*Droid, error) { 174 if d, ok := r.droid[id]; ok { 175 return &d, nil 176 } 177 return nil, nil 178 } 179 180 func (r *queryResolver) Human(ctx context.Context, id string) (*Human, error) { 181 if h, ok := r.humans[id]; ok { 182 return &h, nil 183 } 184 return nil, nil 185 } 186 187 func (r *queryResolver) Starship(ctx context.Context, id string) (*Starship, error) { 188 if s, ok := r.starships[id]; ok { 189 return &s, nil 190 } 191 return nil, nil 192 } 193 194 type starshipResolver struct{ *Resolver } 195 196 func (r *starshipResolver) Length(ctx context.Context, obj *Starship, unit *LengthUnit) (float64, error) { 197 switch *unit { 198 case LengthUnitMeter, "": 199 return obj.Length, nil 200 case LengthUnitFoot: 201 return obj.Length * 3.28084, nil 202 default: 203 return 0, errors.New("invalid unit") 204 } 205 } 206 207 func NewResolver() Config { 208 r := Resolver{} 209 r.humans = map[string]Human{ 210 "1000": { 211 CharacterFields: CharacterFields{ 212 ID: "1000", 213 Name: "Luke Skywalker", 214 FriendIds: []string{"1002", "1003", "2000", "2001"}, 215 AppearsIn: []Episode{EpisodeNewhope, EpisodeEmpire, EpisodeJedi}, 216 }, 217 heightMeters: 1.72, 218 Mass: 77, 219 StarshipIds: []string{"3001", "3003"}, 220 }, 221 "1001": { 222 CharacterFields: CharacterFields{ 223 ID: "1001", 224 Name: "Darth Vader", 225 FriendIds: []string{"1004"}, 226 AppearsIn: []Episode{EpisodeNewhope, EpisodeEmpire, EpisodeJedi}, 227 }, 228 heightMeters: 2.02, 229 Mass: 136, 230 StarshipIds: []string{"3002"}, 231 }, 232 "1002": { 233 CharacterFields: CharacterFields{ 234 ID: "1002", 235 Name: "Han Solo", 236 FriendIds: []string{"1000", "1003", "2001"}, 237 AppearsIn: []Episode{EpisodeNewhope, EpisodeEmpire, EpisodeJedi}, 238 }, 239 heightMeters: 1.8, 240 Mass: 80, 241 StarshipIds: []string{"3000", "3003"}, 242 }, 243 "1003": { 244 CharacterFields: CharacterFields{ 245 ID: "1003", 246 Name: "Leia Organa", 247 FriendIds: []string{"1000", "1002", "2000", "2001"}, 248 AppearsIn: []Episode{EpisodeNewhope, EpisodeEmpire, EpisodeJedi}, 249 }, 250 heightMeters: 1.5, 251 Mass: 49, 252 }, 253 "1004": { 254 CharacterFields: CharacterFields{ 255 ID: "1004", 256 Name: "Wilhuff Tarkin", 257 FriendIds: []string{"1001"}, 258 AppearsIn: []Episode{EpisodeNewhope}, 259 }, 260 heightMeters: 1.8, 261 Mass: 0, 262 }, 263 } 264 265 r.droid = map[string]Droid{ 266 "2000": { 267 CharacterFields: CharacterFields{ 268 ID: "2000", 269 Name: "C-3PO", 270 FriendIds: []string{"1000", "1002", "1003", "2001"}, 271 AppearsIn: []Episode{EpisodeNewhope, EpisodeEmpire, EpisodeJedi}, 272 }, 273 PrimaryFunction: "Protocol", 274 }, 275 "2001": { 276 CharacterFields: CharacterFields{ 277 ID: "2001", 278 Name: "R2-D2", 279 FriendIds: []string{"1000", "1002", "1003"}, 280 AppearsIn: []Episode{EpisodeNewhope, EpisodeEmpire, EpisodeJedi}, 281 }, 282 PrimaryFunction: "Astromech", 283 }, 284 } 285 286 r.starships = map[string]Starship{ 287 "3000": { 288 ID: "3000", 289 Name: "Millennium Falcon", 290 History: [][]int{ 291 {1, 2}, 292 {4, 5}, 293 {1, 2}, 294 {3, 2}, 295 }, 296 Length: 34.37, 297 }, 298 "3001": { 299 ID: "3001", 300 Name: "X-Wing", 301 History: [][]int{ 302 {6, 4}, 303 {3, 2}, 304 {2, 3}, 305 {5, 1}, 306 }, 307 Length: 12.5, 308 }, 309 "3002": { 310 ID: "3002", 311 Name: "TIE Advanced x1", 312 History: [][]int{ 313 {3, 2}, 314 {7, 2}, 315 {6, 4}, 316 {3, 2}, 317 }, 318 Length: 9.2, 319 }, 320 "3003": { 321 ID: "3003", 322 Name: "Imperial shuttle", 323 History: [][]int{ 324 {1, 7}, 325 {3, 5}, 326 {5, 3}, 327 {7, 1}, 328 }, 329 Length: 20, 330 }, 331 } 332 333 r.reviews = map[Episode][]Review{} 334 335 return Config{ 336 Resolvers: &r, 337 } 338 }