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