aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/graphql-go/graphql/definition.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/graphql-go/graphql/definition.go')
-rw-r--r--vendor/github.com/graphql-go/graphql/definition.go1340
1 files changed, 1340 insertions, 0 deletions
diff --git a/vendor/github.com/graphql-go/graphql/definition.go b/vendor/github.com/graphql-go/graphql/definition.go
new file mode 100644
index 00000000..dffea080
--- /dev/null
+++ b/vendor/github.com/graphql-go/graphql/definition.go
@@ -0,0 +1,1340 @@
+package graphql
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+ "regexp"
+
+ "github.com/graphql-go/graphql/language/ast"
+)
+
+// Type interface for all of the possible kinds of GraphQL types
+type Type interface {
+ Name() string
+ Description() string
+ String() string
+ Error() error
+}
+
+var _ Type = (*Scalar)(nil)
+var _ Type = (*Object)(nil)
+var _ Type = (*Interface)(nil)
+var _ Type = (*Union)(nil)
+var _ Type = (*Enum)(nil)
+var _ Type = (*InputObject)(nil)
+var _ Type = (*List)(nil)
+var _ Type = (*NonNull)(nil)
+var _ Type = (*Argument)(nil)
+
+// Input interface for types that may be used as input types for arguments and directives.
+type Input interface {
+ Name() string
+ Description() string
+ String() string
+ Error() error
+}
+
+var _ Input = (*Scalar)(nil)
+var _ Input = (*Enum)(nil)
+var _ Input = (*InputObject)(nil)
+var _ Input = (*List)(nil)
+var _ Input = (*NonNull)(nil)
+
+// IsInputType determines if given type is a GraphQLInputType
+func IsInputType(ttype Type) bool {
+ named := GetNamed(ttype)
+ if _, ok := named.(*Scalar); ok {
+ return true
+ }
+ if _, ok := named.(*Enum); ok {
+ return true
+ }
+ if _, ok := named.(*InputObject); ok {
+ return true
+ }
+ return false
+}
+
+// IsOutputType determines if given type is a GraphQLOutputType
+func IsOutputType(ttype Type) bool {
+ name := GetNamed(ttype)
+ if _, ok := name.(*Scalar); ok {
+ return true
+ }
+ if _, ok := name.(*Object); ok {
+ return true
+ }
+ if _, ok := name.(*Interface); ok {
+ return true
+ }
+ if _, ok := name.(*Union); ok {
+ return true
+ }
+ if _, ok := name.(*Enum); ok {
+ return true
+ }
+ return false
+}
+
+// Leaf interface for types that may be leaf values
+type Leaf interface {
+ Name() string
+ Description() string
+ String() string
+ Error() error
+ Serialize(value interface{}) interface{}
+}
+
+var _ Leaf = (*Scalar)(nil)
+var _ Leaf = (*Enum)(nil)
+
+// IsLeafType determines if given type is a leaf value
+func IsLeafType(ttype Type) bool {
+ named := GetNamed(ttype)
+ if _, ok := named.(*Scalar); ok {
+ return true
+ }
+ if _, ok := named.(*Enum); ok {
+ return true
+ }
+ return false
+}
+
+// Output interface for types that may be used as output types as the result of fields.
+type Output interface {
+ Name() string
+ Description() string
+ String() string
+ Error() error
+}
+
+var _ Output = (*Scalar)(nil)
+var _ Output = (*Object)(nil)
+var _ Output = (*Interface)(nil)
+var _ Output = (*Union)(nil)
+var _ Output = (*Enum)(nil)
+var _ Output = (*List)(nil)
+var _ Output = (*NonNull)(nil)
+
+// Composite interface for types that may describe the parent context of a selection set.
+type Composite interface {
+ Name() string
+ Description() string
+ String() string
+ Error() error
+}
+
+var _ Composite = (*Object)(nil)
+var _ Composite = (*Interface)(nil)
+var _ Composite = (*Union)(nil)
+
+// IsCompositeType determines if given type is a GraphQLComposite type
+func IsCompositeType(ttype interface{}) bool {
+ if _, ok := ttype.(*Object); ok {
+ return true
+ }
+ if _, ok := ttype.(*Interface); ok {
+ return true
+ }
+ if _, ok := ttype.(*Union); ok {
+ return true
+ }
+ return false
+}
+
+// Abstract interface for types that may describe the parent context of a selection set.
+type Abstract interface {
+ Name() string
+}
+
+var _ Abstract = (*Interface)(nil)
+var _ Abstract = (*Union)(nil)
+
+func IsAbstractType(ttype interface{}) bool {
+ if _, ok := ttype.(*Interface); ok {
+ return true
+ }
+ if _, ok := ttype.(*Union); ok {
+ return true
+ }
+ return false
+}
+
+// Nullable interface for types that can accept null as a value.
+type Nullable interface {
+}
+
+var _ Nullable = (*Scalar)(nil)
+var _ Nullable = (*Object)(nil)
+var _ Nullable = (*Interface)(nil)
+var _ Nullable = (*Union)(nil)
+var _ Nullable = (*Enum)(nil)
+var _ Nullable = (*InputObject)(nil)
+var _ Nullable = (*List)(nil)
+
+// GetNullable returns the Nullable type of the given GraphQL type
+func GetNullable(ttype Type) Nullable {
+ if ttype, ok := ttype.(*NonNull); ok {
+ return ttype.OfType
+ }
+ return ttype
+}
+
+// Named interface for types that do not include modifiers like List or NonNull.
+type Named interface {
+ String() string
+}
+
+var _ Named = (*Scalar)(nil)
+var _ Named = (*Object)(nil)
+var _ Named = (*Interface)(nil)
+var _ Named = (*Union)(nil)
+var _ Named = (*Enum)(nil)
+var _ Named = (*InputObject)(nil)
+
+// GetNamed returns the Named type of the given GraphQL type
+func GetNamed(ttype Type) Named {
+ unmodifiedType := ttype
+ for {
+ if ttype, ok := unmodifiedType.(*List); ok {
+ unmodifiedType = ttype.OfType
+ continue
+ }
+ if ttype, ok := unmodifiedType.(*NonNull); ok {
+ unmodifiedType = ttype.OfType
+ continue
+ }
+ break
+ }
+ return unmodifiedType
+}
+
+// Scalar Type Definition
+//
+// The leaf values of any request and input values to arguments are
+// Scalars (or Enums) and are defined with a name and a series of functions
+// used to parse input from ast or variables and to ensure validity.
+//
+// Example:
+//
+// var OddType = new Scalar({
+// name: 'Odd',
+// serialize(value) {
+// return value % 2 === 1 ? value : null;
+// }
+// });
+//
+type Scalar struct {
+ PrivateName string `json:"name"`
+ PrivateDescription string `json:"description"`
+
+ scalarConfig ScalarConfig
+ err error
+}
+
+// SerializeFn is a function type for serializing a GraphQLScalar type value
+type SerializeFn func(value interface{}) interface{}
+
+// ParseValueFn is a function type for parsing the value of a GraphQLScalar type
+type ParseValueFn func(value interface{}) interface{}
+
+// ParseLiteralFn is a function type for parsing the literal value of a GraphQLScalar type
+type ParseLiteralFn func(valueAST ast.Value) interface{}
+
+// ScalarConfig options for creating a new GraphQLScalar
+type ScalarConfig struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Serialize SerializeFn
+ ParseValue ParseValueFn
+ ParseLiteral ParseLiteralFn
+}
+
+// NewScalar creates a new GraphQLScalar
+func NewScalar(config ScalarConfig) *Scalar {
+ st := &Scalar{}
+ err := invariant(config.Name != "", "Type must be named.")
+ if err != nil {
+ st.err = err
+ return st
+ }
+
+ err = assertValidName(config.Name)
+ if err != nil {
+ st.err = err
+ return st
+ }
+
+ st.PrivateName = config.Name
+ st.PrivateDescription = config.Description
+
+ err = invariantf(
+ config.Serialize != nil,
+ `%v must provide "serialize" function. If this custom Scalar is `+
+ `also used as an input type, ensure "parseValue" and "parseLiteral" `+
+ `functions are also provided.`, st,
+ )
+ if err != nil {
+ st.err = err
+ return st
+ }
+ if config.ParseValue != nil || config.ParseLiteral != nil {
+ err = invariantf(
+ config.ParseValue != nil && config.ParseLiteral != nil,
+ `%v must provide both "parseValue" and "parseLiteral" functions.`, st,
+ )
+ if err != nil {
+ st.err = err
+ return st
+ }
+ }
+
+ st.scalarConfig = config
+ return st
+}
+func (st *Scalar) Serialize(value interface{}) interface{} {
+ if st.scalarConfig.Serialize == nil {
+ return value
+ }
+ return st.scalarConfig.Serialize(value)
+}
+func (st *Scalar) ParseValue(value interface{}) interface{} {
+ if st.scalarConfig.ParseValue == nil {
+ return value
+ }
+ return st.scalarConfig.ParseValue(value)
+}
+func (st *Scalar) ParseLiteral(valueAST ast.Value) interface{} {
+ if st.scalarConfig.ParseLiteral == nil {
+ return nil
+ }
+ return st.scalarConfig.ParseLiteral(valueAST)
+}
+func (st *Scalar) Name() string {
+ return st.PrivateName
+}
+func (st *Scalar) Description() string {
+ return st.PrivateDescription
+
+}
+func (st *Scalar) String() string {
+ return st.PrivateName
+}
+func (st *Scalar) Error() error {
+ return st.err
+}
+
+// Object Type Definition
+//
+// Almost all of the GraphQL types you define will be object Object types
+// have a name, but most importantly describe their fields.
+// Example:
+//
+// var AddressType = new Object({
+// name: 'Address',
+// fields: {
+// street: { type: String },
+// number: { type: Int },
+// formatted: {
+// type: String,
+// resolve(obj) {
+// return obj.number + ' ' + obj.street
+// }
+// }
+// }
+// });
+//
+// When two types need to refer to each other, or a type needs to refer to
+// itself in a field, you can use a function expression (aka a closure or a
+// thunk) to supply the fields lazily.
+//
+// Example:
+//
+// var PersonType = new Object({
+// name: 'Person',
+// fields: () => ({
+// name: { type: String },
+// bestFriend: { type: PersonType },
+// })
+// });
+//
+// /
+type Object struct {
+ PrivateName string `json:"name"`
+ PrivateDescription string `json:"description"`
+ IsTypeOf IsTypeOfFn
+
+ typeConfig ObjectConfig
+ initialisedFields bool
+ fields FieldDefinitionMap
+ initialisedInterfaces bool
+ interfaces []*Interface
+ // Interim alternative to throwing an error during schema definition at run-time
+ err error
+}
+
+// IsTypeOfParams Params for IsTypeOfFn()
+type IsTypeOfParams struct {
+ // Value that needs to be resolve.
+ // Use this to decide which GraphQLObject this value maps to.
+ Value interface{}
+
+ // Info is a collection of information about the current execution state.
+ Info ResolveInfo
+
+ // Context argument is a context value that is provided to every resolve function within an execution.
+ // It is commonly
+ // used to represent an authenticated user, or request-specific caches.
+ Context context.Context
+}
+
+type IsTypeOfFn func(p IsTypeOfParams) bool
+
+type InterfacesThunk func() []*Interface
+
+type ObjectConfig struct {
+ Name string `json:"name"`
+ Interfaces interface{} `json:"interfaces"`
+ Fields interface{} `json:"fields"`
+ IsTypeOf IsTypeOfFn `json:"isTypeOf"`
+ Description string `json:"description"`
+}
+
+type FieldsThunk func() Fields
+
+func NewObject(config ObjectConfig) *Object {
+ objectType := &Object{}
+
+ err := invariant(config.Name != "", "Type must be named.")
+ if err != nil {
+ objectType.err = err
+ return objectType
+ }
+ err = assertValidName(config.Name)
+ if err != nil {
+ objectType.err = err
+ return objectType
+ }
+
+ objectType.PrivateName = config.Name
+ objectType.PrivateDescription = config.Description
+ objectType.IsTypeOf = config.IsTypeOf
+ objectType.typeConfig = config
+
+ return objectType
+}
+func (gt *Object) AddFieldConfig(fieldName string, fieldConfig *Field) {
+ if fieldName == "" || fieldConfig == nil {
+ return
+ }
+ switch gt.typeConfig.Fields.(type) {
+ case Fields:
+ gt.typeConfig.Fields.(Fields)[fieldName] = fieldConfig
+ gt.initialisedFields = false
+ }
+}
+func (gt *Object) Name() string {
+ return gt.PrivateName
+}
+func (gt *Object) Description() string {
+ return ""
+}
+func (gt *Object) String() string {
+ return gt.PrivateName
+}
+func (gt *Object) Fields() FieldDefinitionMap {
+ if gt.initialisedFields {
+ return gt.fields
+ }
+
+ var configureFields Fields
+ switch gt.typeConfig.Fields.(type) {
+ case Fields:
+ configureFields = gt.typeConfig.Fields.(Fields)
+ case FieldsThunk:
+ configureFields = gt.typeConfig.Fields.(FieldsThunk)()
+ }
+
+ fields, err := defineFieldMap(gt, configureFields)
+ gt.err = err
+ gt.fields = fields
+ gt.initialisedFields = true
+ return gt.fields
+}
+
+func (gt *Object) Interfaces() []*Interface {
+ if gt.initialisedInterfaces {
+ return gt.interfaces
+ }
+
+ var configInterfaces []*Interface
+ switch gt.typeConfig.Interfaces.(type) {
+ case InterfacesThunk:
+ configInterfaces = gt.typeConfig.Interfaces.(InterfacesThunk)()
+ case []*Interface:
+ configInterfaces = gt.typeConfig.Interfaces.([]*Interface)
+ case nil:
+ default:
+ gt.err = fmt.Errorf("Unknown Object.Interfaces type: %T", gt.typeConfig.Interfaces)
+ gt.initialisedInterfaces = true
+ return nil
+ }
+
+ interfaces, err := defineInterfaces(gt, configInterfaces)
+ gt.err = err
+ gt.interfaces = interfaces
+ gt.initialisedInterfaces = true
+ return gt.interfaces
+}
+
+func (gt *Object) Error() error {
+ return gt.err
+}
+
+func defineInterfaces(ttype *Object, interfaces []*Interface) ([]*Interface, error) {
+ ifaces := []*Interface{}
+
+ if len(interfaces) == 0 {
+ return ifaces, nil
+ }
+ for _, iface := range interfaces {
+ err := invariantf(
+ iface != nil,
+ `%v may only implement Interface types, it cannot implement: %v.`, ttype, iface,
+ )
+ if err != nil {
+ return ifaces, err
+ }
+ if iface.ResolveType != nil {
+ err = invariantf(
+ iface.ResolveType != nil,
+ `Interface Type %v does not provide a "resolveType" function `+
+ `and implementing Type %v does not provide a "isTypeOf" `+
+ `function. There is no way to resolve this implementing type `+
+ `during execution.`, iface, ttype,
+ )
+ if err != nil {
+ return ifaces, err
+ }
+ }
+ ifaces = append(ifaces, iface)
+ }
+
+ return ifaces, nil
+}
+
+func defineFieldMap(ttype Named, fieldMap Fields) (FieldDefinitionMap, error) {
+ resultFieldMap := FieldDefinitionMap{}
+
+ err := invariantf(
+ len(fieldMap) > 0,
+ `%v fields must be an object with field names as keys or a function which return such an object.`, ttype,
+ )
+ if err != nil {
+ return resultFieldMap, err
+ }
+
+ for fieldName, field := range fieldMap {
+ if field == nil {
+ continue
+ }
+ err = invariantf(
+ field.Type != nil,
+ `%v.%v field type must be Output Type but got: %v.`, ttype, fieldName, field.Type,
+ )
+ if err != nil {
+ return resultFieldMap, err
+ }
+ if field.Type.Error() != nil {
+ return resultFieldMap, field.Type.Error()
+ }
+ err = assertValidName(fieldName)
+ if err != nil {
+ return resultFieldMap, err
+ }
+ fieldDef := &FieldDefinition{
+ Name: fieldName,
+ Description: field.Description,
+ Type: field.Type,
+ Resolve: field.Resolve,
+ DeprecationReason: field.DeprecationReason,
+ }
+
+ fieldDef.Args = []*Argument{}
+ for argName, arg := range field.Args {
+ err := assertValidName(argName)
+ if err != nil {
+ return resultFieldMap, err
+ }
+ err = invariantf(
+ arg != nil,
+ `%v.%v args must be an object with argument names as keys.`, ttype, fieldName,
+ )
+ if err != nil {
+ return resultFieldMap, err
+ }
+ err = invariantf(
+ arg.Type != nil,
+ `%v.%v(%v:) argument type must be Input Type but got: %v.`, ttype, fieldName, argName, arg.Type,
+ )
+ if err != nil {
+ return resultFieldMap, err
+ }
+ fieldArg := &Argument{
+ PrivateName: argName,
+ PrivateDescription: arg.Description,
+ Type: arg.Type,
+ DefaultValue: arg.DefaultValue,
+ }
+ fieldDef.Args = append(fieldDef.Args, fieldArg)
+ }
+ resultFieldMap[fieldName] = fieldDef
+ }
+ return resultFieldMap, nil
+}
+
+// ResolveParams Params for FieldResolveFn()
+type ResolveParams struct {
+ // Source is the source value
+ Source interface{}
+
+ // Args is a map of arguments for current GraphQL request
+ Args map[string]interface{}
+
+ // Info is a collection of information about the current execution state.
+ Info ResolveInfo
+
+ // Context argument is a context value that is provided to every resolve function within an execution.
+ // It is commonly
+ // used to represent an authenticated user, or request-specific caches.
+ Context context.Context
+}
+
+type FieldResolveFn func(p ResolveParams) (interface{}, error)
+
+type ResolveInfo struct {
+ FieldName string
+ FieldASTs []*ast.Field
+ ReturnType Output
+ ParentType Composite
+ Schema Schema
+ Fragments map[string]ast.Definition
+ RootValue interface{}
+ Operation ast.Definition
+ VariableValues map[string]interface{}
+}
+
+type Fields map[string]*Field
+
+type Field struct {
+ Name string `json:"name"` // used by graphlql-relay
+ Type Output `json:"type"`
+ Args FieldConfigArgument `json:"args"`
+ Resolve FieldResolveFn `json:"-"`
+ DeprecationReason string `json:"deprecationReason"`
+ Description string `json:"description"`
+}
+
+type FieldConfigArgument map[string]*ArgumentConfig
+
+type ArgumentConfig struct {
+ Type Input `json:"type"`
+ DefaultValue interface{} `json:"defaultValue"`
+ Description string `json:"description"`
+}
+
+type FieldDefinitionMap map[string]*FieldDefinition
+type FieldDefinition struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Type Output `json:"type"`
+ Args []*Argument `json:"args"`
+ Resolve FieldResolveFn `json:"-"`
+ DeprecationReason string `json:"deprecationReason"`
+}
+
+type FieldArgument struct {
+ Name string `json:"name"`
+ Type Type `json:"type"`
+ DefaultValue interface{} `json:"defaultValue"`
+ Description string `json:"description"`
+}
+
+type Argument struct {
+ PrivateName string `json:"name"`
+ Type Input `json:"type"`
+ DefaultValue interface{} `json:"defaultValue"`
+ PrivateDescription string `json:"description"`
+}
+
+func (st *Argument) Name() string {
+ return st.PrivateName
+}
+func (st *Argument) Description() string {
+ return st.PrivateDescription
+
+}
+func (st *Argument) String() string {
+ return st.PrivateName
+}
+func (st *Argument) Error() error {
+ return nil
+}
+
+// Interface Type Definition
+//
+// When a field can return one of a heterogeneous set of types, a Interface type
+// is used to describe what types are possible, what fields are in common across
+// all types, as well as a function to determine which type is actually used
+// when the field is resolved.
+//
+// Example:
+//
+// var EntityType = new Interface({
+// name: 'Entity',
+// fields: {
+// name: { type: String }
+// }
+// });
+//
+//
+type Interface struct {
+ PrivateName string `json:"name"`
+ PrivateDescription string `json:"description"`
+ ResolveType ResolveTypeFn
+
+ typeConfig InterfaceConfig
+ initialisedFields bool
+ fields FieldDefinitionMap
+ err error
+}
+type InterfaceConfig struct {
+ Name string `json:"name"`
+ Fields interface{} `json:"fields"`
+ ResolveType ResolveTypeFn
+ Description string `json:"description"`
+}
+
+// ResolveTypeParams Params for ResolveTypeFn()
+type ResolveTypeParams struct {
+ // Value that needs to be resolve.
+ // Use this to decide which GraphQLObject this value maps to.
+ Value interface{}
+
+ // Info is a collection of information about the current execution state.
+ Info ResolveInfo
+
+ // Context argument is a context value that is provided to every resolve function within an execution.
+ // It is commonly
+ // used to represent an authenticated user, or request-specific caches.
+ Context context.Context
+}
+
+type ResolveTypeFn func(p ResolveTypeParams) *Object
+
+func NewInterface(config InterfaceConfig) *Interface {
+ it := &Interface{}
+
+ err := invariant(config.Name != "", "Type must be named.")
+ if err != nil {
+ it.err = err
+ return it
+ }
+ err = assertValidName(config.Name)
+ if err != nil {
+ it.err = err
+ return it
+ }
+ it.PrivateName = config.Name
+ it.PrivateDescription = config.Description
+ it.ResolveType = config.ResolveType
+ it.typeConfig = config
+
+ return it
+}
+
+func (it *Interface) AddFieldConfig(fieldName string, fieldConfig *Field) {
+ if fieldName == "" || fieldConfig == nil {
+ return
+ }
+ switch it.typeConfig.Fields.(type) {
+ case Fields:
+ it.typeConfig.Fields.(Fields)[fieldName] = fieldConfig
+ it.initialisedFields = false
+ }
+}
+
+func (it *Interface) Name() string {
+ return it.PrivateName
+}
+
+func (it *Interface) Description() string {
+ return it.PrivateDescription
+}
+
+func (it *Interface) Fields() (fields FieldDefinitionMap) {
+ if it.initialisedFields {
+ return it.fields
+ }
+
+ var configureFields Fields
+ switch it.typeConfig.Fields.(type) {
+ case Fields:
+ configureFields = it.typeConfig.Fields.(Fields)
+ case FieldsThunk:
+ configureFields = it.typeConfig.Fields.(FieldsThunk)()
+ }
+
+ fields, err := defineFieldMap(it, configureFields)
+ it.err = err
+ it.fields = fields
+ it.initialisedFields = true
+ return it.fields
+}
+
+func (it *Interface) String() string {
+ return it.PrivateName
+}
+
+func (it *Interface) Error() error {
+ return it.err
+}
+
+// Union Type Definition
+//
+// When a field can return one of a heterogeneous set of types, a Union type
+// is used to describe what types are possible as well as providing a function
+// to determine which type is actually used when the field is resolved.
+//
+// Example:
+//
+// var PetType = new Union({
+// name: 'Pet',
+// types: [ DogType, CatType ],
+// resolveType(value) {
+// if (value instanceof Dog) {
+// return DogType;
+// }
+// if (value instanceof Cat) {
+// return CatType;
+// }
+// }
+// });
+type Union struct {
+ PrivateName string `json:"name"`
+ PrivateDescription string `json:"description"`
+ ResolveType ResolveTypeFn
+
+ typeConfig UnionConfig
+ types []*Object
+ possibleTypes map[string]bool
+
+ err error
+}
+type UnionConfig struct {
+ Name string `json:"name"`
+ Types []*Object `json:"types"`
+ ResolveType ResolveTypeFn
+ Description string `json:"description"`
+}
+
+func NewUnion(config UnionConfig) *Union {
+ objectType := &Union{}
+
+ err := invariant(config.Name != "", "Type must be named.")
+ if err != nil {
+ objectType.err = err
+ return objectType
+ }
+ err = assertValidName(config.Name)
+ if err != nil {
+ objectType.err = err
+ return objectType
+ }
+ objectType.PrivateName = config.Name
+ objectType.PrivateDescription = config.Description
+ objectType.ResolveType = config.ResolveType
+
+ err = invariantf(
+ len(config.Types) > 0,
+ `Must provide Array of types for Union %v.`, config.Name,
+ )
+ if err != nil {
+ objectType.err = err
+ return objectType
+ }
+ for _, ttype := range config.Types {
+ err := invariantf(
+ ttype != nil,
+ `%v may only contain Object types, it cannot contain: %v.`, objectType, ttype,
+ )
+ if err != nil {
+ objectType.err = err
+ return objectType
+ }
+ if objectType.ResolveType == nil {
+ err = invariantf(
+ ttype.IsTypeOf != nil,
+ `Union Type %v does not provide a "resolveType" function `+
+ `and possible Type %v does not provide a "isTypeOf" `+
+ `function. There is no way to resolve this possible type `+
+ `during execution.`, objectType, ttype,
+ )
+ if err != nil {
+ objectType.err = err
+ return objectType
+ }
+ }
+ }
+ objectType.types = config.Types
+ objectType.typeConfig = config
+
+ return objectType
+}
+func (ut *Union) Types() []*Object {
+ return ut.types
+}
+func (ut *Union) String() string {
+ return ut.PrivateName
+}
+func (ut *Union) Name() string {
+ return ut.PrivateName
+}
+func (ut *Union) Description() string {
+ return ut.PrivateDescription
+}
+func (ut *Union) Error() error {
+ return ut.err
+}
+
+// Enum Type Definition
+//
+// Some leaf values of requests and input values are Enums. GraphQL serializes
+// Enum values as strings, however internally Enums can be represented by any
+// kind of type, often integers.
+//
+// Example:
+//
+// var RGBType = new Enum({
+// name: 'RGB',
+// values: {
+// RED: { value: 0 },
+// GREEN: { value: 1 },
+// BLUE: { value: 2 }
+// }
+// });
+//
+// Note: If a value is not provided in a definition, the name of the enum value
+// will be used as its internal value.
+
+type Enum struct {
+ PrivateName string `json:"name"`
+ PrivateDescription string `json:"description"`
+
+ enumConfig EnumConfig
+ values []*EnumValueDefinition
+ valuesLookup map[interface{}]*EnumValueDefinition
+ nameLookup map[string]*EnumValueDefinition
+
+ err error
+}
+type EnumValueConfigMap map[string]*EnumValueConfig
+type EnumValueConfig struct {
+ Value interface{} `json:"value"`
+ DeprecationReason string `json:"deprecationReason"`
+ Description string `json:"description"`
+}
+type EnumConfig struct {
+ Name string `json:"name"`
+ Values EnumValueConfigMap `json:"values"`
+ Description string `json:"description"`
+}
+type EnumValueDefinition struct {
+ Name string `json:"name"`
+ Value interface{} `json:"value"`
+ DeprecationReason string `json:"deprecationReason"`
+ Description string `json:"description"`
+}
+
+func NewEnum(config EnumConfig) *Enum {
+ gt := &Enum{}
+ gt.enumConfig = config
+
+ err := assertValidName(config.Name)
+ if err != nil {
+ gt.err = err
+ return gt
+ }
+
+ gt.PrivateName = config.Name
+ gt.PrivateDescription = config.Description
+ gt.values, err = gt.defineEnumValues(config.Values)
+ if err != nil {
+ gt.err = err
+ return gt
+ }
+
+ return gt
+}
+func (gt *Enum) defineEnumValues(valueMap EnumValueConfigMap) ([]*EnumValueDefinition, error) {
+ values := []*EnumValueDefinition{}
+
+ err := invariantf(
+ len(valueMap) > 0,
+ `%v values must be an object with value names as keys.`, gt,
+ )
+ if err != nil {
+ return values, err
+ }
+
+ for valueName, valueConfig := range valueMap {
+ err := invariantf(
+ valueConfig != nil,
+ `%v.%v must refer to an object with a "value" key `+
+ `representing an internal value but got: %v.`, gt, valueName, valueConfig,
+ )
+ if err != nil {
+ return values, err
+ }
+ err = assertValidName(valueName)
+ if err != nil {
+ return values, err
+ }
+ value := &EnumValueDefinition{
+ Name: valueName,
+ Value: valueConfig.Value,
+ DeprecationReason: valueConfig.DeprecationReason,
+ Description: valueConfig.Description,
+ }
+ if value.Value == nil {
+ value.Value = valueName
+ }
+ values = append(values, value)
+ }
+ return values, nil
+}
+func (gt *Enum) Values() []*EnumValueDefinition {
+ return gt.values
+}
+func (gt *Enum) Serialize(value interface{}) interface{} {
+ v := value
+ if reflect.ValueOf(v).Kind() == reflect.Ptr {
+ v = reflect.Indirect(reflect.ValueOf(v)).Interface()
+ }
+ if enumValue, ok := gt.getValueLookup()[v]; ok {
+ return enumValue.Name
+ }
+ return nil
+}
+func (gt *Enum) ParseValue(value interface{}) interface{} {
+ var v string
+
+ switch value := value.(type) {
+ case string:
+ v = value
+ case *string:
+ v = *value
+ default:
+ return nil
+ }
+ if enumValue, ok := gt.getNameLookup()[v]; ok {
+ return enumValue.Value
+ }
+ return nil
+}
+func (gt *Enum) ParseLiteral(valueAST ast.Value) interface{} {
+ if valueAST, ok := valueAST.(*ast.EnumValue); ok {
+ if enumValue, ok := gt.getNameLookup()[valueAST.Value]; ok {
+ return enumValue.Value
+ }
+ }
+ return nil
+}
+func (gt *Enum) Name() string {
+ return gt.PrivateName
+}
+func (gt *Enum) Description() string {
+ return gt.PrivateDescription
+}
+func (gt *Enum) String() string {
+ return gt.PrivateName
+}
+func (gt *Enum) Error() error {
+ return gt.err
+}
+func (gt *Enum) getValueLookup() map[interface{}]*EnumValueDefinition {
+ if len(gt.valuesLookup) > 0 {
+ return gt.valuesLookup
+ }
+ valuesLookup := map[interface{}]*EnumValueDefinition{}
+ for _, value := range gt.Values() {
+ valuesLookup[value.Value] = value
+ }
+ gt.valuesLookup = valuesLookup
+ return gt.valuesLookup
+}
+
+func (gt *Enum) getNameLookup() map[string]*EnumValueDefinition {
+ if len(gt.nameLookup) > 0 {
+ return gt.nameLookup
+ }
+ nameLookup := map[string]*EnumValueDefinition{}
+ for _, value := range gt.Values() {
+ nameLookup[value.Name] = value
+ }
+ gt.nameLookup = nameLookup
+ return gt.nameLookup
+}
+
+// InputObject Type Definition
+//
+// An input object defines a structured collection of fields which may be
+// supplied to a field argument.
+//
+// Using `NonNull` will ensure that a value must be provided by the query
+//
+// Example:
+//
+// var GeoPoint = new InputObject({
+// name: 'GeoPoint',
+// fields: {
+// lat: { type: new NonNull(Float) },
+// lon: { type: new NonNull(Float) },
+// alt: { type: Float, defaultValue: 0 },
+// }
+// });
+type InputObject struct {
+ PrivateName string `json:"name"`
+ PrivateDescription string `json:"description"`
+
+ typeConfig InputObjectConfig
+ fields InputObjectFieldMap
+ init bool
+ err error
+}
+type InputObjectFieldConfig struct {
+ Type Input `json:"type"`
+ DefaultValue interface{} `json:"defaultValue"`
+ Description string `json:"description"`
+}
+type InputObjectField struct {
+ PrivateName string `json:"name"`
+ Type Input `json:"type"`
+ DefaultValue interface{} `json:"defaultValue"`
+ PrivateDescription string `json:"description"`
+}
+
+func (st *InputObjectField) Name() string {
+ return st.PrivateName
+}
+func (st *InputObjectField) Description() string {
+ return st.PrivateDescription
+
+}
+func (st *InputObjectField) String() string {
+ return st.PrivateName
+}
+func (st *InputObjectField) Error() error {
+ return nil
+}
+
+type InputObjectConfigFieldMap map[string]*InputObjectFieldConfig
+type InputObjectFieldMap map[string]*InputObjectField
+type InputObjectConfigFieldMapThunk func() InputObjectConfigFieldMap
+type InputObjectConfig struct {
+ Name string `json:"name"`
+ Fields interface{} `json:"fields"`
+ Description string `json:"description"`
+}
+
+func NewInputObject(config InputObjectConfig) *InputObject {
+ gt := &InputObject{}
+ err := invariant(config.Name != "", "Type must be named.")
+ if err != nil {
+ gt.err = err
+ return gt
+ }
+
+ gt.PrivateName = config.Name
+ gt.PrivateDescription = config.Description
+ gt.typeConfig = config
+ //gt.fields = gt.defineFieldMap()
+ return gt
+}
+
+func (gt *InputObject) defineFieldMap() InputObjectFieldMap {
+ var fieldMap InputObjectConfigFieldMap
+ switch gt.typeConfig.Fields.(type) {
+ case InputObjectConfigFieldMap:
+ fieldMap = gt.typeConfig.Fields.(InputObjectConfigFieldMap)
+ case InputObjectConfigFieldMapThunk:
+ fieldMap = gt.typeConfig.Fields.(InputObjectConfigFieldMapThunk)()
+ }
+ resultFieldMap := InputObjectFieldMap{}
+
+ err := invariantf(
+ len(fieldMap) > 0,
+ `%v fields must be an object with field names as keys or a function which return such an object.`, gt,
+ )
+ if err != nil {
+ gt.err = err
+ return resultFieldMap
+ }
+
+ for fieldName, fieldConfig := range fieldMap {
+ if fieldConfig == nil {
+ continue
+ }
+ err := assertValidName(fieldName)
+ if err != nil {
+ continue
+ }
+ err = invariantf(
+ fieldConfig.Type != nil,
+ `%v.%v field type must be Input Type but got: %v.`, gt, fieldName, fieldConfig.Type,
+ )
+ if err != nil {
+ gt.err = err
+ return resultFieldMap
+ }
+ field := &InputObjectField{}
+ field.PrivateName = fieldName
+ field.Type = fieldConfig.Type
+ field.PrivateDescription = fieldConfig.Description
+ field.DefaultValue = fieldConfig.DefaultValue
+ resultFieldMap[fieldName] = field
+ }
+ gt.init = true
+ return resultFieldMap
+}
+
+func (gt *InputObject) Fields() InputObjectFieldMap {
+ if !gt.init {
+ gt.fields = gt.defineFieldMap()
+ }
+ return gt.fields
+}
+func (gt *InputObject) Name() string {
+ return gt.PrivateName
+}
+func (gt *InputObject) Description() string {
+ return gt.PrivateDescription
+}
+func (gt *InputObject) String() string {
+ return gt.PrivateName
+}
+func (gt *InputObject) Error() error {
+ return gt.err
+}
+
+// List Modifier
+//
+// A list is a kind of type marker, a wrapping type which points to another
+// type. Lists are often created within the context of defining the fields of
+// an object type.
+//
+// Example:
+//
+// var PersonType = new Object({
+// name: 'Person',
+// fields: () => ({
+// parents: { type: new List(Person) },
+// children: { type: new List(Person) },
+// })
+// })
+//
+type List struct {
+ OfType Type `json:"ofType"`
+
+ err error
+}
+
+func NewList(ofType Type) *List {
+ gl := &List{}
+
+ err := invariantf(ofType != nil, `Can only create List of a Type but got: %v.`, ofType)
+ if err != nil {
+ gl.err = err
+ return gl
+ }
+
+ gl.OfType = ofType
+ return gl
+}
+func (gl *List) Name() string {
+ return fmt.Sprintf("%v", gl.OfType)
+}
+func (gl *List) Description() string {
+ return ""
+}
+func (gl *List) String() string {
+ if gl.OfType != nil {
+ return fmt.Sprintf("[%v]", gl.OfType)
+ }
+ return ""
+}
+func (gl *List) Error() error {
+ return gl.err
+}
+
+// NonNull Modifier
+//
+// A non-null is a kind of type marker, a wrapping type which points to another
+// type. Non-null types enforce that their values are never null and can ensure
+// an error is raised if this ever occurs during a request. It is useful for
+// fields which you can make a strong guarantee on non-nullability, for example
+// usually the id field of a database row will never be null.
+//
+// Example:
+//
+// var RowType = new Object({
+// name: 'Row',
+// fields: () => ({
+// id: { type: new NonNull(String) },
+// })
+// })
+//
+// Note: the enforcement of non-nullability occurs within the executor.
+type NonNull struct {
+ OfType Type `json:"ofType"`
+
+ err error
+}
+
+func NewNonNull(ofType Type) *NonNull {
+ gl := &NonNull{}
+
+ _, isOfTypeNonNull := ofType.(*NonNull)
+ err := invariantf(ofType != nil && !isOfTypeNonNull, `Can only create NonNull of a Nullable Type but got: %v.`, ofType)
+ if err != nil {
+ gl.err = err
+ return gl
+ }
+ gl.OfType = ofType
+ return gl
+}
+func (gl *NonNull) Name() string {
+ return fmt.Sprintf("%v!", gl.OfType)
+}
+func (gl *NonNull) Description() string {
+ return ""
+}
+func (gl *NonNull) String() string {
+ if gl.OfType != nil {
+ return gl.Name()
+ }
+ return ""
+}
+func (gl *NonNull) Error() error {
+ return gl.err
+}
+
+var NameRegExp, _ = regexp.Compile("^[_a-zA-Z][_a-zA-Z0-9]*$")
+
+func assertValidName(name string) error {
+ return invariantf(
+ NameRegExp.MatchString(name),
+ `Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "%v" does not.`, name)
+
+}