forked from samsarahq/thunder
/
types.go
132 lines (110 loc) · 3.6 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package schemabuilder
import "reflect"
// A Object represents a Go type and set of methods to be converted into an
// Object in a GraphQL schema.
type Object struct {
Name string // Optional, defaults to Type's name.
Description string
Type interface{}
Methods Methods // Deprecated, use FieldFunc instead.
key string
}
type paginationObject struct {
Name string
Fn interface{}
}
// FieldFuncOption is an interface for the variadic options that can be passed
// to a FieldFunc for configuring options on that function.
type FieldFuncOption interface {
apply(*method)
}
// fieldFuncOptionFunc is a helper to define FieldFuncOptions from a func.
type fieldFuncOptionFunc func(*method)
func (f fieldFuncOptionFunc) apply(m *method) { f(m) }
// NonNullable is an option that can be passed to a FieldFunc to indicate that
// its return value is required, even if the return value is a pointer type.
var NonNullable fieldFuncOptionFunc = func(m *method) {
m.MarkedNonNullable = true
}
// Paginated is an option that can be passed to a FieldFunc to indicate that
// its return value should be paginated.
var Paginated fieldFuncOptionFunc = func(m *method) {
m.Paginated = true
}
type TextFilterFields map[string]interface{}
func (s TextFilterFields) apply(m *method) {
m.TextFilterFuncs = s
}
type SortFields map[string]interface{}
func (s SortFields) apply(m *method) {
m.SortFuncs = s
}
// FieldFunc exposes a field on an object. The function f can take a number of
// optional arguments:
// func([ctx context.Context], [o *Type], [args struct {}]) ([Result], [error])
//
// For example, for an object of type User, a fullName field might take just an
// instance of the object:
// user.FieldFunc("fullName", func(u *User) string {
// return u.FirstName + " " + u.LastName
// })
//
// An addUser mutation field might take both a context and arguments:
// mutation.FieldFunc("addUser", func(ctx context.Context, args struct{
// FirstName string
// LastName string
// }) (int, error) {
// userID, err := db.AddUser(ctx, args.FirstName, args.LastName)
// return userID, err
// })
func (s *Object) FieldFunc(name string, f interface{}, options ...FieldFuncOption) {
if s.Methods == nil {
s.Methods = make(Methods)
}
m := &method{Fn: f}
for _, opt := range options {
opt.apply(m)
}
if _, ok := s.Methods[name]; ok {
panic("duplicate method")
}
s.Methods[name] = m
}
// Key registers the key field on an object. The field should be specified by the name of the
// graphql field.
// For example, for an object User:
// type struct User {
// UserKey int64
// }
// The key will be registered as:
// object.Key("userKey")
func (s *Object) Key(f string) {
s.key = f
}
type method struct {
MarkedNonNullable bool
Fn interface{}
// Whether or not the FieldFunc is paginated.
Paginated bool
// Text filter methods
TextFilterFuncs map[string]interface{}
// Sort methods
SortFuncs map[string]interface{}
}
// A Methods map represents the set of methods exposed on a Object.
type Methods map[string]*method
// Union is a special marker struct that can be embedded into to denote
// that a type should be treated as a union type by the schemabuilder.
//
// For example, to denote that a return value that may be a *Asset or
// *Vehicle might look like:
// type GatewayUnion struct {
// schemabuilder.Union
// *Asset
// *Vehicle
// }
//
// Fields returning a union type should expect to return this type as a
// one-hot struct, i.e. only Asset or Vehicle should be specified, but not both.
type Union struct{}
var unionType = reflect.TypeOf(Union{})