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
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}
1341