definition.go

   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}