github.com/deliveroo/gqlgen@v0.7.2/example/scalars/model/model.go (about)

     1  package model
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"strconv"
     8  	"strings"
     9  	"time"
    10  
    11  	"external"
    12  
    13  	"github.com/99designs/gqlgen/graphql"
    14  )
    15  
    16  type Banned bool
    17  
    18  type User struct {
    19  	ID       external.ObjectID
    20  	Name     string
    21  	Created  time.Time // direct binding to builtin types with external Marshal/Unmarshal methods
    22  	IsBanned Banned    // aliased primitive
    23  	Address  Address
    24  	Tier     Tier
    25  }
    26  
    27  // Point is serialized as a simple array, eg [1, 2]
    28  type Point struct {
    29  	X int
    30  	Y int
    31  }
    32  
    33  func (p *Point) UnmarshalGQL(v interface{}) error {
    34  	pointStr, ok := v.(string)
    35  	if !ok {
    36  		return fmt.Errorf("points must be strings")
    37  	}
    38  
    39  	parts := strings.Split(pointStr, ",")
    40  
    41  	if len(parts) != 2 {
    42  		return fmt.Errorf("points must have 2 parts")
    43  	}
    44  
    45  	var err error
    46  	if p.X, err = strconv.Atoi(parts[0]); err != nil {
    47  		return err
    48  	}
    49  	if p.Y, err = strconv.Atoi(parts[1]); err != nil {
    50  		return err
    51  	}
    52  	return nil
    53  }
    54  
    55  // MarshalGQL implements the graphql.Marshaler interface
    56  func (p Point) MarshalGQL(w io.Writer) {
    57  	fmt.Fprintf(w, `"%d,%d"`, p.X, p.Y)
    58  }
    59  
    60  // if the type referenced in .gqlgen.yml is a function that returns a marshaller we can use it to encode and decode
    61  // onto any existing go type.
    62  func MarshalTimestamp(t time.Time) graphql.Marshaler {
    63  	return graphql.WriterFunc(func(w io.Writer) {
    64  		io.WriteString(w, strconv.FormatInt(t.Unix(), 10))
    65  	})
    66  }
    67  
    68  // Unmarshal{Typename} is only required if the scalar appears as an input. The raw values have already been decoded
    69  // from json into int/float64/bool/nil/map[string]interface/[]interface
    70  func UnmarshalTimestamp(v interface{}) (time.Time, error) {
    71  	if tmpStr, ok := v.(int64); ok {
    72  		return time.Unix(tmpStr, 0), nil
    73  	}
    74  	return time.Time{}, errors.New("time should be a unix timestamp")
    75  }
    76  
    77  // Lets redefine the base ID type to use an id from an external library
    78  func MarshalID(id external.ObjectID) graphql.Marshaler {
    79  	return graphql.WriterFunc(func(w io.Writer) {
    80  		io.WriteString(w, strconv.Quote(fmt.Sprintf("=%d=", id)))
    81  	})
    82  }
    83  
    84  // And the same for the unmarshaler
    85  func UnmarshalID(v interface{}) (external.ObjectID, error) {
    86  	str, ok := v.(string)
    87  	if !ok {
    88  		return 0, fmt.Errorf("ids must be strings")
    89  	}
    90  	i, err := strconv.Atoi(str[1 : len(str)-1])
    91  	return external.ObjectID(i), err
    92  }
    93  
    94  type SearchArgs struct {
    95  	Location     *Point
    96  	CreatedAfter *time.Time
    97  	IsBanned     Banned
    98  }
    99  
   100  // A custom enum that uses integers to represent the values in memory but serialize as string for graphql
   101  type Tier uint
   102  
   103  const (
   104  	TierA Tier = iota
   105  	TierB Tier = iota
   106  	TierC Tier = iota
   107  )
   108  
   109  func TierForStr(str string) (Tier, error) {
   110  	switch str {
   111  	case "A":
   112  		return TierA, nil
   113  	case "B":
   114  		return TierB, nil
   115  	case "C":
   116  		return TierC, nil
   117  	default:
   118  		return 0, fmt.Errorf("%s is not a valid Tier", str)
   119  	}
   120  }
   121  
   122  func (e Tier) IsValid() bool {
   123  	switch e {
   124  	case TierA, TierB, TierC:
   125  		return true
   126  	}
   127  	return false
   128  }
   129  
   130  func (e Tier) String() string {
   131  	switch e {
   132  	case TierA:
   133  		return "A"
   134  	case TierB:
   135  		return "B"
   136  	case TierC:
   137  		return "C"
   138  	default:
   139  		panic("invalid enum value")
   140  	}
   141  }
   142  
   143  func (e *Tier) UnmarshalGQL(v interface{}) error {
   144  	str, ok := v.(string)
   145  	if !ok {
   146  		return fmt.Errorf("enums must be strings")
   147  	}
   148  
   149  	var err error
   150  	*e, err = TierForStr(str)
   151  	return err
   152  }
   153  
   154  func (e Tier) MarshalGQL(w io.Writer) {
   155  	fmt.Fprint(w, strconv.Quote(e.String()))
   156  }