1package graphql
2
3import (
4 "context"
5 "fmt"
6 "reflect"
7 "regexp"
8
9 "github.com/graphql-go/graphql/language/ast"
10)
11
12// Type interface for all of the possible kinds of GraphQL types
13type Type interface {
14 Name() string
15 Description() string
16 String() string
17 Error() error
18}
19
20var _ Type = (*Scalar)(nil)
21var _ Type = (*Object)(nil)
22var _ Type = (*Interface)(nil)
23var _ Type = (*Union)(nil)
24var _ Type = (*Enum)(nil)
25var _ Type = (*InputObject)(nil)
26var _ Type = (*List)(nil)
27var _ Type = (*NonNull)(nil)
28var _ Type = (*Argument)(nil)
29
30// Input interface for types that may be used as input types for arguments and directives.
31type Input interface {
32 Name() string
33 Description() string
34 String() string
35 Error() error
36}
37
38var _ Input = (*Scalar)(nil)
39var _ Input = (*Enum)(nil)
40var _ Input = (*InputObject)(nil)
41var _ Input = (*List)(nil)
42var _ Input = (*NonNull)(nil)
43
44// IsInputType determines if given type is a GraphQLInputType
45func IsInputType(ttype Type) bool {
46 named := GetNamed(ttype)
47 if _, ok := named.(*Scalar); ok {
48 return true
49 }
50 if _, ok := named.(*Enum); ok {
51 return true
52 }
53 if _, ok := named.(*InputObject); ok {
54 return true
55 }
56 return false
57}
58
59// IsOutputType determines if given type is a GraphQLOutputType
60func IsOutputType(ttype Type) bool {
61 name := GetNamed(ttype)
62 if _, ok := name.(*Scalar); ok {
63 return true
64 }
65 if _, ok := name.(*Object); ok {
66 return true
67 }
68 if _, ok := name.(*Interface); ok {
69 return true
70 }
71 if _, ok := name.(*Union); ok {
72 return true
73 }
74 if _, ok := name.(*Enum); ok {
75 return true
76 }
77 return false
78}
79
80// Leaf interface for types that may be leaf values
81type Leaf interface {
82 Name() string
83 Description() string
84 String() string
85 Error() error
86 Serialize(value interface{}) interface{}
87}
88
89var _ Leaf = (*Scalar)(nil)
90var _ Leaf = (*Enum)(nil)
91
92// IsLeafType determines if given type is a leaf value
93func IsLeafType(ttype Type) bool {
94 named := GetNamed(ttype)
95 if _, ok := named.(*Scalar); ok {
96 return true
97 }
98 if _, ok := named.(*Enum); ok {
99 return true
100 }
101 return false
102}
103
104// Output interface for types that may be used as output types as the result of fields.
105type Output interface {
106 Name() string
107 Description() string
108 String() string
109 Error() error
110}
111
112var _ Output = (*Scalar)(nil)
113var _ Output = (*Object)(nil)
114var _ Output = (*Interface)(nil)
115var _ Output = (*Union)(nil)
116var _ Output = (*Enum)(nil)
117var _ Output = (*List)(nil)
118var _ Output = (*NonNull)(nil)
119
120// Composite interface for types that may describe the parent context of a selection set.
121type Composite interface {
122 Name() string
123 Description() string
124 String() string
125 Error() error
126}
127
128var _ Composite = (*Object)(nil)
129var _ Composite = (*Interface)(nil)
130var _ Composite = (*Union)(nil)
131
132// IsCompositeType determines if given type is a GraphQLComposite type
133func IsCompositeType(ttype interface{}) bool {
134 if _, ok := ttype.(*Object); ok {
135 return true
136 }
137 if _, ok := ttype.(*Interface); ok {
138 return true
139 }
140 if _, ok := ttype.(*Union); ok {
141 return true
142 }
143 return false
144}
145
146// Abstract interface for types that may describe the parent context of a selection set.
147type Abstract interface {
148 Name() string
149}
150
151var _ Abstract = (*Interface)(nil)
152var _ Abstract = (*Union)(nil)
153
154func IsAbstractType(ttype interface{}) bool {
155 if _, ok := ttype.(*Interface); ok {
156 return true
157 }
158 if _, ok := ttype.(*Union); ok {
159 return true
160 }
161 return false
162}
163
164// Nullable interface for types that can accept null as a value.
165type Nullable interface {
166}
167
168var _ Nullable = (*Scalar)(nil)
169var _ Nullable = (*Object)(nil)
170var _ Nullable = (*Interface)(nil)
171var _ Nullable = (*Union)(nil)
172var _ Nullable = (*Enum)(nil)
173var _ Nullable = (*InputObject)(nil)
174var _ Nullable = (*List)(nil)
175
176// GetNullable returns the Nullable type of the given GraphQL type
177func GetNullable(ttype Type) Nullable {
178 if ttype, ok := ttype.(*NonNull); ok {
179 return ttype.OfType
180 }
181 return ttype
182}
183
184// Named interface for types that do not include modifiers like List or NonNull.
185type Named interface {
186 String() string
187}
188
189var _ Named = (*Scalar)(nil)
190var _ Named = (*Object)(nil)
191var _ Named = (*Interface)(nil)
192var _ Named = (*Union)(nil)
193var _ Named = (*Enum)(nil)
194var _ Named = (*InputObject)(nil)
195
196// GetNamed returns the Named type of the given GraphQL type
197func GetNamed(ttype Type) Named {
198 unmodifiedType := ttype
199 for {
200 if ttype, ok := unmodifiedType.(*List); ok {
201 unmodifiedType = ttype.OfType
202 continue
203 }
204 if ttype, ok := unmodifiedType.(*NonNull); ok {
205 unmodifiedType = ttype.OfType
206 continue
207 }
208 break
209 }
210 return unmodifiedType
211}
212
213// Scalar Type Definition
214//
215// The leaf values of any request and input values to arguments are
216// Scalars (or Enums) and are defined with a name and a series of functions
217// used to parse input from ast or variables and to ensure validity.
218//
219// Example:
220//
221// var OddType = new Scalar({
222// name: 'Odd',
223// serialize(value) {
224// return value % 2 === 1 ? value : null;
225// }
226// });
227//
228type Scalar struct {
229 PrivateName string `json:"name"`
230 PrivateDescription string `json:"description"`
231
232 scalarConfig ScalarConfig
233 err error
234}
235
236// SerializeFn is a function type for serializing a GraphQLScalar type value
237type SerializeFn func(value interface{}) interface{}
238
239// ParseValueFn is a function type for parsing the value of a GraphQLScalar type
240type ParseValueFn func(value interface{}) interface{}
241
242// ParseLiteralFn is a function type for parsing the literal value of a GraphQLScalar type
243type ParseLiteralFn func(valueAST ast.Value) interface{}
244
245// ScalarConfig options for creating a new GraphQLScalar
246type ScalarConfig struct {
247 Name string `json:"name"`
248 Description string `json:"description"`
249 Serialize SerializeFn
250 ParseValue ParseValueFn
251 ParseLiteral ParseLiteralFn
252}
253
254// NewScalar creates a new GraphQLScalar
255func NewScalar(config ScalarConfig) *Scalar {
256 st := &Scalar{}
257 err := invariant(config.Name != "", "Type must be named.")
258 if err != nil {
259 st.err = err
260 return st
261 }
262
263 err = assertValidName(config.Name)
264 if err != nil {
265 st.err = err
266 return st
267 }
268
269 st.PrivateName = config.Name
270 st.PrivateDescription = config.Description
271
272 err = invariantf(
273 config.Serialize != nil,
274 `%v must provide "serialize" function. If this custom Scalar is `+
275 `also used as an input type, ensure "parseValue" and "parseLiteral" `+
276 `functions are also provided.`, st,
277 )
278 if err != nil {
279 st.err = err
280 return st
281 }
282 if config.ParseValue != nil || config.ParseLiteral != nil {
283 err = invariantf(
284 config.ParseValue != nil && config.ParseLiteral != nil,
285 `%v must provide both "parseValue" and "parseLiteral" functions.`, st,
286 )
287 if err != nil {
288 st.err = err
289 return st
290 }
291 }
292
293 st.scalarConfig = config
294 return st
295}
296func (st *Scalar) Serialize(value interface{}) interface{} {
297 if st.scalarConfig.Serialize == nil {
298 return value
299 }
300 return st.scalarConfig.Serialize(value)
301}
302func (st *Scalar) ParseValue(value interface{}) interface{} {
303 if st.scalarConfig.ParseValue == nil {
304 return value
305 }
306 return st.scalarConfig.ParseValue(value)
307}
308func (st *Scalar) ParseLiteral(valueAST ast.Value) interface{} {
309 if st.scalarConfig.ParseLiteral == nil {
310 return nil
311 }
312 return st.scalarConfig.ParseLiteral(valueAST)
313}
314func (st *Scalar) Name() string {
315 return st.PrivateName
316}
317func (st *Scalar) Description() string {
318 return st.PrivateDescription
319
320}
321func (st *Scalar) String() string {
322 return st.PrivateName
323}
324func (st *Scalar) Error() error {
325 return st.err
326}
327
328// Object Type Definition
329//
330// Almost all of the GraphQL types you define will be object Object types
331// have a name, but most importantly describe their fields.
332// Example:
333//
334// var AddressType = new Object({
335// name: 'Address',
336// fields: {
337// street: { type: String },
338// number: { type: Int },
339// formatted: {
340// type: String,
341// resolve(obj) {
342// return obj.number + ' ' + obj.street
343// }
344// }
345// }
346// });
347//
348// When two types need to refer to each other, or a type needs to refer to
349// itself in a field, you can use a function expression (aka a closure or a
350// thunk) to supply the fields lazily.
351//
352// Example:
353//
354// var PersonType = new Object({
355// name: 'Person',
356// fields: () => ({
357// name: { type: String },
358// bestFriend: { type: PersonType },
359// })
360// });
361//
362// /
363type Object struct {
364 PrivateName string `json:"name"`
365 PrivateDescription string `json:"description"`
366 IsTypeOf IsTypeOfFn
367
368 typeConfig ObjectConfig
369 initialisedFields bool
370 fields FieldDefinitionMap
371 initialisedInterfaces bool
372 interfaces []*Interface
373 // Interim alternative to throwing an error during schema definition at run-time
374 err error
375}
376
377// IsTypeOfParams Params for IsTypeOfFn()
378type IsTypeOfParams struct {
379 // Value that needs to be resolve.
380 // Use this to decide which GraphQLObject this value maps to.
381 Value interface{}
382
383 // Info is a collection of information about the current execution state.
384 Info ResolveInfo
385
386 // Context argument is a context value that is provided to every resolve function within an execution.
387 // It is commonly
388 // used to represent an authenticated user, or request-specific caches.
389 Context context.Context
390}
391
392type IsTypeOfFn func(p IsTypeOfParams) bool
393
394type InterfacesThunk func() []*Interface
395
396type ObjectConfig struct {
397 Name string `json:"name"`
398 Interfaces interface{} `json:"interfaces"`
399 Fields interface{} `json:"fields"`
400 IsTypeOf IsTypeOfFn `json:"isTypeOf"`
401 Description string `json:"description"`
402}
403
404type FieldsThunk func() Fields
405
406func NewObject(config ObjectConfig) *Object {
407 objectType := &Object{}
408
409 err := invariant(config.Name != "", "Type must be named.")
410 if err != nil {
411 objectType.err = err
412 return objectType
413 }
414 err = assertValidName(config.Name)
415 if err != nil {
416 objectType.err = err
417 return objectType
418 }
419
420 objectType.PrivateName = config.Name
421 objectType.PrivateDescription = config.Description
422 objectType.IsTypeOf = config.IsTypeOf
423 objectType.typeConfig = config
424
425 return objectType
426}
427func (gt *Object) AddFieldConfig(fieldName string, fieldConfig *Field) {
428 if fieldName == "" || fieldConfig == nil {
429 return
430 }
431 switch gt.typeConfig.Fields.(type) {
432 case Fields:
433 gt.typeConfig.Fields.(Fields)[fieldName] = fieldConfig
434 gt.initialisedFields = false
435 }
436}
437func (gt *Object) Name() string {
438 return gt.PrivateName
439}
440func (gt *Object) Description() string {
441 return ""
442}
443func (gt *Object) String() string {
444 return gt.PrivateName
445}
446func (gt *Object) Fields() FieldDefinitionMap {
447 if gt.initialisedFields {
448 return gt.fields
449 }
450
451 var configureFields Fields
452 switch gt.typeConfig.Fields.(type) {
453 case Fields:
454 configureFields = gt.typeConfig.Fields.(Fields)
455 case FieldsThunk:
456 configureFields = gt.typeConfig.Fields.(FieldsThunk)()
457 }
458
459 fields, err := defineFieldMap(gt, configureFields)
460 gt.err = err
461 gt.fields = fields
462 gt.initialisedFields = true
463 return gt.fields
464}
465
466func (gt *Object) Interfaces() []*Interface {
467 if gt.initialisedInterfaces {
468 return gt.interfaces
469 }
470
471 var configInterfaces []*Interface
472 switch gt.typeConfig.Interfaces.(type) {
473 case InterfacesThunk:
474 configInterfaces = gt.typeConfig.Interfaces.(InterfacesThunk)()
475 case []*Interface:
476 configInterfaces = gt.typeConfig.Interfaces.([]*Interface)
477 case nil:
478 default:
479 gt.err = fmt.Errorf("Unknown Object.Interfaces type: %T", gt.typeConfig.Interfaces)
480 gt.initialisedInterfaces = true
481 return nil
482 }
483
484 interfaces, err := defineInterfaces(gt, configInterfaces)
485 gt.err = err
486 gt.interfaces = interfaces
487 gt.initialisedInterfaces = true
488 return gt.interfaces
489}
490
491func (gt *Object) Error() error {
492 return gt.err
493}
494
495func defineInterfaces(ttype *Object, interfaces []*Interface) ([]*Interface, error) {
496 ifaces := []*Interface{}
497
498 if len(interfaces) == 0 {
499 return ifaces, nil
500 }
501 for _, iface := range interfaces {
502 err := invariantf(
503 iface != nil,
504 `%v may only implement Interface types, it cannot implement: %v.`, ttype, iface,
505 )
506 if err != nil {
507 return ifaces, err
508 }
509 if iface.ResolveType != nil {
510 err = invariantf(
511 iface.ResolveType != nil,
512 `Interface Type %v does not provide a "resolveType" function `+
513 `and implementing Type %v does not provide a "isTypeOf" `+
514 `function. There is no way to resolve this implementing type `+
515 `during execution.`, iface, ttype,
516 )
517 if err != nil {
518 return ifaces, err
519 }
520 }
521 ifaces = append(ifaces, iface)
522 }
523
524 return ifaces, nil
525}
526
527func defineFieldMap(ttype Named, fieldMap Fields) (FieldDefinitionMap, error) {
528 resultFieldMap := FieldDefinitionMap{}
529
530 err := invariantf(
531 len(fieldMap) > 0,
532 `%v fields must be an object with field names as keys or a function which return such an object.`, ttype,
533 )
534 if err != nil {
535 return resultFieldMap, err
536 }
537
538 for fieldName, field := range fieldMap {
539 if field == nil {
540 continue
541 }
542 err = invariantf(
543 field.Type != nil,
544 `%v.%v field type must be Output Type but got: %v.`, ttype, fieldName, field.Type,
545 )
546 if err != nil {
547 return resultFieldMap, err
548 }
549 if field.Type.Error() != nil {
550 return resultFieldMap, field.Type.Error()
551 }
552 err = assertValidName(fieldName)
553 if err != nil {
554 return resultFieldMap, err
555 }
556 fieldDef := &FieldDefinition{
557 Name: fieldName,
558 Description: field.Description,
559 Type: field.Type,
560 Resolve: field.Resolve,
561 DeprecationReason: field.DeprecationReason,
562 }
563
564 fieldDef.Args = []*Argument{}
565 for argName, arg := range field.Args {
566 err := assertValidName(argName)
567 if err != nil {
568 return resultFieldMap, err
569 }
570 err = invariantf(
571 arg != nil,
572 `%v.%v args must be an object with argument names as keys.`, ttype, fieldName,
573 )
574 if err != nil {
575 return resultFieldMap, err
576 }
577 err = invariantf(
578 arg.Type != nil,
579 `%v.%v(%v:) argument type must be Input Type but got: %v.`, ttype, fieldName, argName, arg.Type,
580 )
581 if err != nil {
582 return resultFieldMap, err
583 }
584 fieldArg := &Argument{
585 PrivateName: argName,
586 PrivateDescription: arg.Description,
587 Type: arg.Type,
588 DefaultValue: arg.DefaultValue,
589 }
590 fieldDef.Args = append(fieldDef.Args, fieldArg)
591 }
592 resultFieldMap[fieldName] = fieldDef
593 }
594 return resultFieldMap, nil
595}
596
597// ResolveParams Params for FieldResolveFn()
598type ResolveParams struct {
599 // Source is the source value
600 Source interface{}
601
602 // Args is a map of arguments for current GraphQL request
603 Args map[string]interface{}
604
605 // Info is a collection of information about the current execution state.
606 Info ResolveInfo
607
608 // Context argument is a context value that is provided to every resolve function within an execution.
609 // It is commonly
610 // used to represent an authenticated user, or request-specific caches.
611 Context context.Context
612}
613
614type FieldResolveFn func(p ResolveParams) (interface{}, error)
615
616type ResolveInfo struct {
617 FieldName string
618 FieldASTs []*ast.Field
619 ReturnType Output
620 ParentType Composite
621 Schema Schema
622 Fragments map[string]ast.Definition
623 RootValue interface{}
624 Operation ast.Definition
625 VariableValues map[string]interface{}
626}
627
628type Fields map[string]*Field
629
630type Field struct {
631 Name string `json:"name"` // used by graphlql-relay
632 Type Output `json:"type"`
633 Args FieldConfigArgument `json:"args"`
634 Resolve FieldResolveFn `json:"-"`
635 DeprecationReason string `json:"deprecationReason"`
636 Description string `json:"description"`
637}
638
639type FieldConfigArgument map[string]*ArgumentConfig
640
641type ArgumentConfig struct {
642 Type Input `json:"type"`
643 DefaultValue interface{} `json:"defaultValue"`
644 Description string `json:"description"`
645}
646
647type FieldDefinitionMap map[string]*FieldDefinition
648type FieldDefinition struct {
649 Name string `json:"name"`
650 Description string `json:"description"`
651 Type Output `json:"type"`
652 Args []*Argument `json:"args"`
653 Resolve FieldResolveFn `json:"-"`
654 DeprecationReason string `json:"deprecationReason"`
655}
656
657type FieldArgument struct {
658 Name string `json:"name"`
659 Type Type `json:"type"`
660 DefaultValue interface{} `json:"defaultValue"`
661 Description string `json:"description"`
662}
663
664type Argument struct {
665 PrivateName string `json:"name"`
666 Type Input `json:"type"`
667 DefaultValue interface{} `json:"defaultValue"`
668 PrivateDescription string `json:"description"`
669}
670
671func (st *Argument) Name() string {
672 return st.PrivateName
673}
674func (st *Argument) Description() string {
675 return st.PrivateDescription
676
677}
678func (st *Argument) String() string {
679 return st.PrivateName
680}
681func (st *Argument) Error() error {
682 return nil
683}
684
685// Interface Type Definition
686//
687// When a field can return one of a heterogeneous set of types, a Interface type
688// is used to describe what types are possible, what fields are in common across
689// all types, as well as a function to determine which type is actually used
690// when the field is resolved.
691//
692// Example:
693//
694// var EntityType = new Interface({
695// name: 'Entity',
696// fields: {
697// name: { type: String }
698// }
699// });
700//
701//
702type Interface struct {
703 PrivateName string `json:"name"`
704 PrivateDescription string `json:"description"`
705 ResolveType ResolveTypeFn
706
707 typeConfig InterfaceConfig
708 initialisedFields bool
709 fields FieldDefinitionMap
710 err error
711}
712type InterfaceConfig struct {
713 Name string `json:"name"`
714 Fields interface{} `json:"fields"`
715 ResolveType ResolveTypeFn
716 Description string `json:"description"`
717}
718
719// ResolveTypeParams Params for ResolveTypeFn()
720type ResolveTypeParams struct {
721 // Value that needs to be resolve.
722 // Use this to decide which GraphQLObject this value maps to.
723 Value interface{}
724
725 // Info is a collection of information about the current execution state.
726 Info ResolveInfo
727
728 // Context argument is a context value that is provided to every resolve function within an execution.
729 // It is commonly
730 // used to represent an authenticated user, or request-specific caches.
731 Context context.Context
732}
733
734type ResolveTypeFn func(p ResolveTypeParams) *Object
735
736func NewInterface(config InterfaceConfig) *Interface {
737 it := &Interface{}
738
739 err := invariant(config.Name != "", "Type must be named.")
740 if err != nil {
741 it.err = err
742 return it
743 }
744 err = assertValidName(config.Name)
745 if err != nil {
746 it.err = err
747 return it
748 }
749 it.PrivateName = config.Name
750 it.PrivateDescription = config.Description
751 it.ResolveType = config.ResolveType
752 it.typeConfig = config
753
754 return it
755}
756
757func (it *Interface) AddFieldConfig(fieldName string, fieldConfig *Field) {
758 if fieldName == "" || fieldConfig == nil {
759 return
760 }
761 switch it.typeConfig.Fields.(type) {
762 case Fields:
763 it.typeConfig.Fields.(Fields)[fieldName] = fieldConfig
764 it.initialisedFields = false
765 }
766}
767
768func (it *Interface) Name() string {
769 return it.PrivateName
770}
771
772func (it *Interface) Description() string {
773 return it.PrivateDescription
774}
775
776func (it *Interface) Fields() (fields FieldDefinitionMap) {
777 if it.initialisedFields {
778 return it.fields
779 }
780
781 var configureFields Fields
782 switch it.typeConfig.Fields.(type) {
783 case Fields:
784 configureFields = it.typeConfig.Fields.(Fields)
785 case FieldsThunk:
786 configureFields = it.typeConfig.Fields.(FieldsThunk)()
787 }
788
789 fields, err := defineFieldMap(it, configureFields)
790 it.err = err
791 it.fields = fields
792 it.initialisedFields = true
793 return it.fields
794}
795
796func (it *Interface) String() string {
797 return it.PrivateName
798}
799
800func (it *Interface) Error() error {
801 return it.err
802}
803
804// Union Type Definition
805//
806// When a field can return one of a heterogeneous set of types, a Union type
807// is used to describe what types are possible as well as providing a function
808// to determine which type is actually used when the field is resolved.
809//
810// Example:
811//
812// var PetType = new Union({
813// name: 'Pet',
814// types: [ DogType, CatType ],
815// resolveType(value) {
816// if (value instanceof Dog) {
817// return DogType;
818// }
819// if (value instanceof Cat) {
820// return CatType;
821// }
822// }
823// });
824type Union struct {
825 PrivateName string `json:"name"`
826 PrivateDescription string `json:"description"`
827 ResolveType ResolveTypeFn
828
829 typeConfig UnionConfig
830 types []*Object
831 possibleTypes map[string]bool
832
833 err error
834}
835type UnionConfig struct {
836 Name string `json:"name"`
837 Types []*Object `json:"types"`
838 ResolveType ResolveTypeFn
839 Description string `json:"description"`
840}
841
842func NewUnion(config UnionConfig) *Union {
843 objectType := &Union{}
844
845 err := invariant(config.Name != "", "Type must be named.")
846 if err != nil {
847 objectType.err = err
848 return objectType
849 }
850 err = assertValidName(config.Name)
851 if err != nil {
852 objectType.err = err
853 return objectType
854 }
855 objectType.PrivateName = config.Name
856 objectType.PrivateDescription = config.Description
857 objectType.ResolveType = config.ResolveType
858
859 err = invariantf(
860 len(config.Types) > 0,
861 `Must provide Array of types for Union %v.`, config.Name,
862 )
863 if err != nil {
864 objectType.err = err
865 return objectType
866 }
867 for _, ttype := range config.Types {
868 err := invariantf(
869 ttype != nil,
870 `%v may only contain Object types, it cannot contain: %v.`, objectType, ttype,
871 )
872 if err != nil {
873 objectType.err = err
874 return objectType
875 }
876 if objectType.ResolveType == nil {
877 err = invariantf(
878 ttype.IsTypeOf != nil,
879 `Union Type %v does not provide a "resolveType" function `+
880 `and possible Type %v does not provide a "isTypeOf" `+
881 `function. There is no way to resolve this possible type `+
882 `during execution.`, objectType, ttype,
883 )
884 if err != nil {
885 objectType.err = err
886 return objectType
887 }
888 }
889 }
890 objectType.types = config.Types
891 objectType.typeConfig = config
892
893 return objectType
894}
895func (ut *Union) Types() []*Object {
896 return ut.types
897}
898func (ut *Union) String() string {
899 return ut.PrivateName
900}
901func (ut *Union) Name() string {
902 return ut.PrivateName
903}
904func (ut *Union) Description() string {
905 return ut.PrivateDescription
906}
907func (ut *Union) Error() error {
908 return ut.err
909}
910
911// Enum Type Definition
912//
913// Some leaf values of requests and input values are Enums. GraphQL serializes
914// Enum values as strings, however internally Enums can be represented by any
915// kind of type, often integers.
916//
917// Example:
918//
919// var RGBType = new Enum({
920// name: 'RGB',
921// values: {
922// RED: { value: 0 },
923// GREEN: { value: 1 },
924// BLUE: { value: 2 }
925// }
926// });
927//
928// Note: If a value is not provided in a definition, the name of the enum value
929// will be used as its internal value.
930
931type Enum struct {
932 PrivateName string `json:"name"`
933 PrivateDescription string `json:"description"`
934
935 enumConfig EnumConfig
936 values []*EnumValueDefinition
937 valuesLookup map[interface{}]*EnumValueDefinition
938 nameLookup map[string]*EnumValueDefinition
939
940 err error
941}
942type EnumValueConfigMap map[string]*EnumValueConfig
943type EnumValueConfig struct {
944 Value interface{} `json:"value"`
945 DeprecationReason string `json:"deprecationReason"`
946 Description string `json:"description"`
947}
948type EnumConfig struct {
949 Name string `json:"name"`
950 Values EnumValueConfigMap `json:"values"`
951 Description string `json:"description"`
952}
953type EnumValueDefinition struct {
954 Name string `json:"name"`
955 Value interface{} `json:"value"`
956 DeprecationReason string `json:"deprecationReason"`
957 Description string `json:"description"`
958}
959
960func NewEnum(config EnumConfig) *Enum {
961 gt := &Enum{}
962 gt.enumConfig = config
963
964 err := assertValidName(config.Name)
965 if err != nil {
966 gt.err = err
967 return gt
968 }
969
970 gt.PrivateName = config.Name
971 gt.PrivateDescription = config.Description
972 gt.values, err = gt.defineEnumValues(config.Values)
973 if err != nil {
974 gt.err = err
975 return gt
976 }
977
978 return gt
979}
980func (gt *Enum) defineEnumValues(valueMap EnumValueConfigMap) ([]*EnumValueDefinition, error) {
981 values := []*EnumValueDefinition{}
982
983 err := invariantf(
984 len(valueMap) > 0,
985 `%v values must be an object with value names as keys.`, gt,
986 )
987 if err != nil {
988 return values, err
989 }
990
991 for valueName, valueConfig := range valueMap {
992 err := invariantf(
993 valueConfig != nil,
994 `%v.%v must refer to an object with a "value" key `+
995 `representing an internal value but got: %v.`, gt, valueName, valueConfig,
996 )
997 if err != nil {
998 return values, err
999 }
1000 err = assertValidName(valueName)
1001 if err != nil {
1002 return values, err
1003 }
1004 value := &EnumValueDefinition{
1005 Name: valueName,
1006 Value: valueConfig.Value,
1007 DeprecationReason: valueConfig.DeprecationReason,
1008 Description: valueConfig.Description,
1009 }
1010 if value.Value == nil {
1011 value.Value = valueName
1012 }
1013 values = append(values, value)
1014 }
1015 return values, nil
1016}
1017func (gt *Enum) Values() []*EnumValueDefinition {
1018 return gt.values
1019}
1020func (gt *Enum) Serialize(value interface{}) interface{} {
1021 v := value
1022 if reflect.ValueOf(v).Kind() == reflect.Ptr {
1023 v = reflect.Indirect(reflect.ValueOf(v)).Interface()
1024 }
1025 if enumValue, ok := gt.getValueLookup()[v]; ok {
1026 return enumValue.Name
1027 }
1028 return nil
1029}
1030func (gt *Enum) ParseValue(value interface{}) interface{} {
1031 var v string
1032
1033 switch value := value.(type) {
1034 case string:
1035 v = value
1036 case *string:
1037 v = *value
1038 default:
1039 return nil
1040 }
1041 if enumValue, ok := gt.getNameLookup()[v]; ok {
1042 return enumValue.Value
1043 }
1044 return nil
1045}
1046func (gt *Enum) ParseLiteral(valueAST ast.Value) interface{} {
1047 if valueAST, ok := valueAST.(*ast.EnumValue); ok {
1048 if enumValue, ok := gt.getNameLookup()[valueAST.Value]; ok {
1049 return enumValue.Value
1050 }
1051 }
1052 return nil
1053}
1054func (gt *Enum) Name() string {
1055 return gt.PrivateName
1056}
1057func (gt *Enum) Description() string {
1058 return gt.PrivateDescription
1059}
1060func (gt *Enum) String() string {
1061 return gt.PrivateName
1062}
1063func (gt *Enum) Error() error {
1064 return gt.err
1065}
1066func (gt *Enum) getValueLookup() map[interface{}]*EnumValueDefinition {
1067 if len(gt.valuesLookup) > 0 {
1068 return gt.valuesLookup
1069 }
1070 valuesLookup := map[interface{}]*EnumValueDefinition{}
1071 for _, value := range gt.Values() {
1072 valuesLookup[value.Value] = value
1073 }
1074 gt.valuesLookup = valuesLookup
1075 return gt.valuesLookup
1076}
1077
1078func (gt *Enum) getNameLookup() map[string]*EnumValueDefinition {
1079 if len(gt.nameLookup) > 0 {
1080 return gt.nameLookup
1081 }
1082 nameLookup := map[string]*EnumValueDefinition{}
1083 for _, value := range gt.Values() {
1084 nameLookup[value.Name] = value
1085 }
1086 gt.nameLookup = nameLookup
1087 return gt.nameLookup
1088}
1089
1090// InputObject Type Definition
1091//
1092// An input object defines a structured collection of fields which may be
1093// supplied to a field argument.
1094//
1095// Using `NonNull` will ensure that a value must be provided by the query
1096//
1097// Example:
1098//
1099// var GeoPoint = new InputObject({
1100// name: 'GeoPoint',
1101// fields: {
1102// lat: { type: new NonNull(Float) },
1103// lon: { type: new NonNull(Float) },
1104// alt: { type: Float, defaultValue: 0 },
1105// }
1106// });
1107type InputObject struct {
1108 PrivateName string `json:"name"`
1109 PrivateDescription string `json:"description"`
1110
1111 typeConfig InputObjectConfig
1112 fields InputObjectFieldMap
1113 init bool
1114 err error
1115}
1116type InputObjectFieldConfig struct {
1117 Type Input `json:"type"`
1118 DefaultValue interface{} `json:"defaultValue"`
1119 Description string `json:"description"`
1120}
1121type InputObjectField struct {
1122 PrivateName string `json:"name"`
1123 Type Input `json:"type"`
1124 DefaultValue interface{} `json:"defaultValue"`
1125 PrivateDescription string `json:"description"`
1126}
1127
1128func (st *InputObjectField) Name() string {
1129 return st.PrivateName
1130}
1131func (st *InputObjectField) Description() string {
1132 return st.PrivateDescription
1133
1134}
1135func (st *InputObjectField) String() string {
1136 return st.PrivateName
1137}
1138func (st *InputObjectField) Error() error {
1139 return nil
1140}
1141
1142type InputObjectConfigFieldMap map[string]*InputObjectFieldConfig
1143type InputObjectFieldMap map[string]*InputObjectField
1144type InputObjectConfigFieldMapThunk func() InputObjectConfigFieldMap
1145type InputObjectConfig struct {
1146 Name string `json:"name"`
1147 Fields interface{} `json:"fields"`
1148 Description string `json:"description"`
1149}
1150
1151func NewInputObject(config InputObjectConfig) *InputObject {
1152 gt := &InputObject{}
1153 err := invariant(config.Name != "", "Type must be named.")
1154 if err != nil {
1155 gt.err = err
1156 return gt
1157 }
1158
1159 gt.PrivateName = config.Name
1160 gt.PrivateDescription = config.Description
1161 gt.typeConfig = config
1162 //gt.fields = gt.defineFieldMap()
1163 return gt
1164}
1165
1166func (gt *InputObject) defineFieldMap() InputObjectFieldMap {
1167 var fieldMap InputObjectConfigFieldMap
1168 switch gt.typeConfig.Fields.(type) {
1169 case InputObjectConfigFieldMap:
1170 fieldMap = gt.typeConfig.Fields.(InputObjectConfigFieldMap)
1171 case InputObjectConfigFieldMapThunk:
1172 fieldMap = gt.typeConfig.Fields.(InputObjectConfigFieldMapThunk)()
1173 }
1174 resultFieldMap := InputObjectFieldMap{}
1175
1176 err := invariantf(
1177 len(fieldMap) > 0,
1178 `%v fields must be an object with field names as keys or a function which return such an object.`, gt,
1179 )
1180 if err != nil {
1181 gt.err = err
1182 return resultFieldMap
1183 }
1184
1185 for fieldName, fieldConfig := range fieldMap {
1186 if fieldConfig == nil {
1187 continue
1188 }
1189 err := assertValidName(fieldName)
1190 if err != nil {
1191 continue
1192 }
1193 err = invariantf(
1194 fieldConfig.Type != nil,
1195 `%v.%v field type must be Input Type but got: %v.`, gt, fieldName, fieldConfig.Type,
1196 )
1197 if err != nil {
1198 gt.err = err
1199 return resultFieldMap
1200 }
1201 field := &InputObjectField{}
1202 field.PrivateName = fieldName
1203 field.Type = fieldConfig.Type
1204 field.PrivateDescription = fieldConfig.Description
1205 field.DefaultValue = fieldConfig.DefaultValue
1206 resultFieldMap[fieldName] = field
1207 }
1208 gt.init = true
1209 return resultFieldMap
1210}
1211
1212func (gt *InputObject) Fields() InputObjectFieldMap {
1213 if !gt.init {
1214 gt.fields = gt.defineFieldMap()
1215 }
1216 return gt.fields
1217}
1218func (gt *InputObject) Name() string {
1219 return gt.PrivateName
1220}
1221func (gt *InputObject) Description() string {
1222 return gt.PrivateDescription
1223}
1224func (gt *InputObject) String() string {
1225 return gt.PrivateName
1226}
1227func (gt *InputObject) Error() error {
1228 return gt.err
1229}
1230
1231// List Modifier
1232//
1233// A list is a kind of type marker, a wrapping type which points to another
1234// type. Lists are often created within the context of defining the fields of
1235// an object type.
1236//
1237// Example:
1238//
1239// var PersonType = new Object({
1240// name: 'Person',
1241// fields: () => ({
1242// parents: { type: new List(Person) },
1243// children: { type: new List(Person) },
1244// })
1245// })
1246//
1247type List struct {
1248 OfType Type `json:"ofType"`
1249
1250 err error
1251}
1252
1253func NewList(ofType Type) *List {
1254 gl := &List{}
1255
1256 err := invariantf(ofType != nil, `Can only create List of a Type but got: %v.`, ofType)
1257 if err != nil {
1258 gl.err = err
1259 return gl
1260 }
1261
1262 gl.OfType = ofType
1263 return gl
1264}
1265func (gl *List) Name() string {
1266 return fmt.Sprintf("%v", gl.OfType)
1267}
1268func (gl *List) Description() string {
1269 return ""
1270}
1271func (gl *List) String() string {
1272 if gl.OfType != nil {
1273 return fmt.Sprintf("[%v]", gl.OfType)
1274 }
1275 return ""
1276}
1277func (gl *List) Error() error {
1278 return gl.err
1279}
1280
1281// NonNull Modifier
1282//
1283// A non-null is a kind of type marker, a wrapping type which points to another
1284// type. Non-null types enforce that their values are never null and can ensure
1285// an error is raised if this ever occurs during a request. It is useful for
1286// fields which you can make a strong guarantee on non-nullability, for example
1287// usually the id field of a database row will never be null.
1288//
1289// Example:
1290//
1291// var RowType = new Object({
1292// name: 'Row',
1293// fields: () => ({
1294// id: { type: new NonNull(String) },
1295// })
1296// })
1297//
1298// Note: the enforcement of non-nullability occurs within the executor.
1299type NonNull struct {
1300 OfType Type `json:"ofType"`
1301
1302 err error
1303}
1304
1305func NewNonNull(ofType Type) *NonNull {
1306 gl := &NonNull{}
1307
1308 _, isOfTypeNonNull := ofType.(*NonNull)
1309 err := invariantf(ofType != nil && !isOfTypeNonNull, `Can only create NonNull of a Nullable Type but got: %v.`, ofType)
1310 if err != nil {
1311 gl.err = err
1312 return gl
1313 }
1314 gl.OfType = ofType
1315 return gl
1316}
1317func (gl *NonNull) Name() string {
1318 return fmt.Sprintf("%v!", gl.OfType)
1319}
1320func (gl *NonNull) Description() string {
1321 return ""
1322}
1323func (gl *NonNull) String() string {
1324 if gl.OfType != nil {
1325 return gl.Name()
1326 }
1327 return ""
1328}
1329func (gl *NonNull) Error() error {
1330 return gl.err
1331}
1332
1333var NameRegExp, _ = regexp.Compile("^[_a-zA-Z][_a-zA-Z0-9]*$")
1334
1335func assertValidName(name string) error {
1336 return invariantf(
1337 NameRegExp.MatchString(name),
1338 `Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "%v" does not.`, name)
1339
1340}