github.com/deliveroo/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  }