github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/example/starwars/resolvers.go (about)

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