aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/graphql-go/graphql/schema.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/graphql-go/graphql/schema.go')
-rw-r--r--vendor/github.com/graphql-go/graphql/schema.go566
1 files changed, 566 insertions, 0 deletions
diff --git a/vendor/github.com/graphql-go/graphql/schema.go b/vendor/github.com/graphql-go/graphql/schema.go
new file mode 100644
index 00000000..f0e6a954
--- /dev/null
+++ b/vendor/github.com/graphql-go/graphql/schema.go
@@ -0,0 +1,566 @@
+package graphql
+
+import (
+ "fmt"
+)
+
+type SchemaConfig struct {
+ Query *Object
+ Mutation *Object
+ Subscription *Object
+ Types []Type
+ Directives []*Directive
+}
+
+type TypeMap map[string]Type
+
+// Schema Definition
+// A Schema is created by supplying the root types of each type of operation,
+// query, mutation (optional) and subscription (optional). A schema definition is then supplied to the
+// validator and executor.
+// Example:
+// myAppSchema, err := NewSchema(SchemaConfig({
+// Query: MyAppQueryRootType,
+// Mutation: MyAppMutationRootType,
+// Subscription: MyAppSubscriptionRootType,
+// });
+// Note: If an array of `directives` are provided to GraphQLSchema, that will be
+// the exact list of directives represented and allowed. If `directives` is not
+// provided then a default set of the specified directives (e.g. @include and
+// @skip) will be used. If you wish to provide *additional* directives to these
+// specified directives, you must explicitly declare them. Example:
+//
+// const MyAppSchema = new GraphQLSchema({
+// ...
+// directives: specifiedDirectives.concat([ myCustomDirective ]),
+// })
+type Schema struct {
+ typeMap TypeMap
+ directives []*Directive
+
+ queryType *Object
+ mutationType *Object
+ subscriptionType *Object
+ implementations map[string][]*Object
+ possibleTypeMap map[string]map[string]bool
+}
+
+func NewSchema(config SchemaConfig) (Schema, error) {
+ var err error
+
+ schema := Schema{}
+
+ err = invariant(config.Query != nil, "Schema query must be Object Type but got: nil.")
+ if err != nil {
+ return schema, err
+ }
+
+ // if schema config contains error at creation time, return those errors
+ if config.Query != nil && config.Query.err != nil {
+ return schema, config.Query.err
+ }
+ if config.Mutation != nil && config.Mutation.err != nil {
+ return schema, config.Mutation.err
+ }
+
+ schema.queryType = config.Query
+ schema.mutationType = config.Mutation
+ schema.subscriptionType = config.Subscription
+
+ // Provide specified directives (e.g. @include and @skip) by default.
+ schema.directives = config.Directives
+ if len(schema.directives) == 0 {
+ schema.directives = SpecifiedDirectives
+ }
+ // Ensure directive definitions are error-free
+ for _, dir := range schema.directives {
+ if dir.err != nil {
+ return schema, dir.err
+ }
+ }
+
+ // Build type map now to detect any errors within this schema.
+ typeMap := TypeMap{}
+ initialTypes := []Type{}
+ if schema.QueryType() != nil {
+ initialTypes = append(initialTypes, schema.QueryType())
+ }
+ if schema.MutationType() != nil {
+ initialTypes = append(initialTypes, schema.MutationType())
+ }
+ if schema.SubscriptionType() != nil {
+ initialTypes = append(initialTypes, schema.SubscriptionType())
+ }
+ if SchemaType != nil {
+ initialTypes = append(initialTypes, SchemaType)
+ }
+
+ for _, ttype := range config.Types {
+ // assume that user will never add a nil object to config
+ initialTypes = append(initialTypes, ttype)
+ }
+
+ for _, ttype := range initialTypes {
+ if ttype.Error() != nil {
+ return schema, ttype.Error()
+ }
+ typeMap, err = typeMapReducer(&schema, typeMap, ttype)
+ if err != nil {
+ return schema, err
+ }
+ }
+
+ schema.typeMap = typeMap
+
+ // Keep track of all implementations by interface name.
+ if schema.implementations == nil {
+ schema.implementations = map[string][]*Object{}
+ }
+ for _, ttype := range schema.typeMap {
+ if ttype, ok := ttype.(*Object); ok {
+ for _, iface := range ttype.Interfaces() {
+ impls, ok := schema.implementations[iface.Name()]
+ if impls == nil || !ok {
+ impls = []*Object{}
+ }
+ impls = append(impls, ttype)
+ schema.implementations[iface.Name()] = impls
+ }
+ }
+ }
+
+ // Enforce correct interface implementations
+ for _, ttype := range schema.typeMap {
+ if ttype, ok := ttype.(*Object); ok {
+ for _, iface := range ttype.Interfaces() {
+ err := assertObjectImplementsInterface(&schema, ttype, iface)
+ if err != nil {
+ return schema, err
+ }
+ }
+ }
+ }
+
+ return schema, nil
+}
+
+
+
+//Added Check implementation of interfaces at runtime..
+//Add Implementations at Runtime..
+func (gq *Schema) AddImplementation() error{
+
+ // Keep track of all implementations by interface name.
+ if gq.implementations == nil {
+ gq.implementations = map[string][]*Object{}
+ }
+ for _, ttype := range gq.typeMap {
+ if ttype, ok := ttype.(*Object); ok {
+ for _, iface := range ttype.Interfaces() {
+ impls, ok := gq.implementations[iface.Name()]
+ if impls == nil || !ok {
+ impls = []*Object{}
+ }
+ impls = append(impls, ttype)
+ gq.implementations[iface.Name()] = impls
+ }
+ }
+ }
+
+ // Enforce correct interface implementations
+ for _, ttype := range gq.typeMap {
+ if ttype, ok := ttype.(*Object); ok {
+ for _, iface := range ttype.Interfaces() {
+ err := assertObjectImplementsInterface(gq, ttype, iface)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+
+//Edited. To check add Types at RunTime..
+//Append Runtime schema to typeMap
+func (gq *Schema)AppendType(objectType Type) error {
+ if objectType.Error() != nil {
+ return objectType.Error()
+ }
+ var err error
+ gq.typeMap, err = typeMapReducer(gq, gq.typeMap, objectType)
+ if err != nil {
+ return err
+ }
+ //Now Add interface implementation..
+ return gq.AddImplementation()
+}
+
+
+
+
+func (gq *Schema) QueryType() *Object {
+ return gq.queryType
+}
+
+func (gq *Schema) MutationType() *Object {
+ return gq.mutationType
+}
+
+func (gq *Schema) SubscriptionType() *Object {
+ return gq.subscriptionType
+}
+
+func (gq *Schema) Directives() []*Directive {
+ return gq.directives
+}
+
+func (gq *Schema) Directive(name string) *Directive {
+ for _, directive := range gq.Directives() {
+ if directive.Name == name {
+ return directive
+ }
+ }
+ return nil
+}
+
+func (gq *Schema) TypeMap() TypeMap {
+ return gq.typeMap
+}
+
+func (gq *Schema) Type(name string) Type {
+ return gq.TypeMap()[name]
+}
+
+func (gq *Schema) PossibleTypes(abstractType Abstract) []*Object {
+ if abstractType, ok := abstractType.(*Union); ok {
+ return abstractType.Types()
+ }
+ if abstractType, ok := abstractType.(*Interface); ok {
+ if impls, ok := gq.implementations[abstractType.Name()]; ok {
+ return impls
+ }
+ }
+ return []*Object{}
+}
+func (gq *Schema) IsPossibleType(abstractType Abstract, possibleType *Object) bool {
+ possibleTypeMap := gq.possibleTypeMap
+ if possibleTypeMap == nil {
+ possibleTypeMap = map[string]map[string]bool{}
+ }
+
+ if typeMap, ok := possibleTypeMap[abstractType.Name()]; !ok {
+ typeMap = map[string]bool{}
+ for _, possibleType := range gq.PossibleTypes(abstractType) {
+ typeMap[possibleType.Name()] = true
+ }
+ possibleTypeMap[abstractType.Name()] = typeMap
+ }
+
+ gq.possibleTypeMap = possibleTypeMap
+ if typeMap, ok := possibleTypeMap[abstractType.Name()]; ok {
+ isPossible, _ := typeMap[possibleType.Name()]
+ return isPossible
+ }
+ return false
+}
+func typeMapReducer(schema *Schema, typeMap TypeMap, objectType Type) (TypeMap, error) {
+ var err error
+ if objectType == nil || objectType.Name() == "" {
+ return typeMap, nil
+ }
+
+ switch objectType := objectType.(type) {
+ case *List:
+ if objectType.OfType != nil {
+ return typeMapReducer(schema, typeMap, objectType.OfType)
+ }
+ case *NonNull:
+ if objectType.OfType != nil {
+ return typeMapReducer(schema, typeMap, objectType.OfType)
+ }
+ case *Object:
+ if objectType.err != nil {
+ return typeMap, objectType.err
+ }
+ }
+
+ if mappedObjectType, ok := typeMap[objectType.Name()]; ok {
+ err = invariantf(
+ mappedObjectType == objectType,
+ `Schema must contain unique named types but contains multiple types named "%v".`, objectType.Name())
+
+ if err != nil {
+ return typeMap, err
+ }
+ return typeMap, err
+ }
+ if objectType.Name() == "" {
+ return typeMap, nil
+ }
+
+ typeMap[objectType.Name()] = objectType
+
+ switch objectType := objectType.(type) {
+ case *Union:
+ types := schema.PossibleTypes(objectType)
+ if objectType.err != nil {
+ return typeMap, objectType.err
+ }
+ for _, innerObjectType := range types {
+ if innerObjectType.err != nil {
+ return typeMap, innerObjectType.err
+ }
+ typeMap, err = typeMapReducer(schema, typeMap, innerObjectType)
+ if err != nil {
+ return typeMap, err
+ }
+ }
+ case *Interface:
+ types := schema.PossibleTypes(objectType)
+ if objectType.err != nil {
+ return typeMap, objectType.err
+ }
+ for _, innerObjectType := range types {
+ if innerObjectType.err != nil {
+ return typeMap, innerObjectType.err
+ }
+ typeMap, err = typeMapReducer(schema, typeMap, innerObjectType)
+ if err != nil {
+ return typeMap, err
+ }
+ }
+ case *Object:
+ interfaces := objectType.Interfaces()
+ if objectType.err != nil {
+ return typeMap, objectType.err
+ }
+ for _, innerObjectType := range interfaces {
+ if innerObjectType.err != nil {
+ return typeMap, innerObjectType.err
+ }
+ typeMap, err = typeMapReducer(schema, typeMap, innerObjectType)
+ if err != nil {
+ return typeMap, err
+ }
+ }
+ }
+
+ switch objectType := objectType.(type) {
+ case *Object:
+ fieldMap := objectType.Fields()
+ if objectType.err != nil {
+ return typeMap, objectType.err
+ }
+ for _, field := range fieldMap {
+ for _, arg := range field.Args {
+ typeMap, err = typeMapReducer(schema, typeMap, arg.Type)
+ if err != nil {
+ return typeMap, err
+ }
+ }
+ typeMap, err = typeMapReducer(schema, typeMap, field.Type)
+ if err != nil {
+ return typeMap, err
+ }
+ }
+ case *Interface:
+ fieldMap := objectType.Fields()
+ if objectType.err != nil {
+ return typeMap, objectType.err
+ }
+ for _, field := range fieldMap {
+ for _, arg := range field.Args {
+ typeMap, err = typeMapReducer(schema, typeMap, arg.Type)
+ if err != nil {
+ return typeMap, err
+ }
+ }
+ typeMap, err = typeMapReducer(schema, typeMap, field.Type)
+ if err != nil {
+ return typeMap, err
+ }
+ }
+ case *InputObject:
+ fieldMap := objectType.Fields()
+ if objectType.err != nil {
+ return typeMap, objectType.err
+ }
+ for _, field := range fieldMap {
+ typeMap, err = typeMapReducer(schema, typeMap, field.Type)
+ if err != nil {
+ return typeMap, err
+ }
+ }
+ }
+ return typeMap, nil
+}
+
+func assertObjectImplementsInterface(schema *Schema, object *Object, iface *Interface) error {
+ objectFieldMap := object.Fields()
+ ifaceFieldMap := iface.Fields()
+
+ // Assert each interface field is implemented.
+ for fieldName := range ifaceFieldMap {
+ objectField := objectFieldMap[fieldName]
+ ifaceField := ifaceFieldMap[fieldName]
+
+ // Assert interface field exists on object.
+ err := invariantf(
+ objectField != nil,
+ `"%v" expects field "%v" but "%v" does not `+
+ `provide it.`, iface, fieldName, object)
+
+ if err != nil {
+ return err
+ }
+
+ // Assert interface field type is satisfied by object field type, by being
+ // a valid subtype. (covariant)
+ err = invariant(
+ isTypeSubTypeOf(schema, objectField.Type, ifaceField.Type),
+ fmt.Sprintf(`%v.%v expects type "%v" but `+
+ `%v.%v provides type "%v".`,
+ iface, fieldName, ifaceField.Type,
+ object, fieldName, objectField.Type),
+ )
+ if err != nil {
+ return err
+ }
+
+ // Assert each interface field arg is implemented.
+ for _, ifaceArg := range ifaceField.Args {
+ argName := ifaceArg.PrivateName
+ var objectArg *Argument
+ for _, arg := range objectField.Args {
+ if arg.PrivateName == argName {
+ objectArg = arg
+ break
+ }
+ }
+ // Assert interface field arg exists on object field.
+ err = invariant(
+ objectArg != nil,
+ fmt.Sprintf(`%v.%v expects argument "%v" but `+
+ `%v.%v does not provide it.`,
+ iface, fieldName, argName,
+ object, fieldName),
+ )
+ if err != nil {
+ return err
+ }
+
+ // Assert interface field arg type matches object field arg type.
+ // (invariant)
+ err = invariant(
+ isEqualType(ifaceArg.Type, objectArg.Type),
+ fmt.Sprintf(
+ `%v.%v(%v:) expects type "%v" `+
+ `but %v.%v(%v:) provides `+
+ `type "%v".`,
+ iface, fieldName, argName, ifaceArg.Type,
+ object, fieldName, argName, objectArg.Type),
+ )
+ if err != nil {
+ return err
+ }
+ }
+ // Assert additional arguments must not be required.
+ for _, objectArg := range objectField.Args {
+ argName := objectArg.PrivateName
+ var ifaceArg *Argument
+ for _, arg := range ifaceField.Args {
+ if arg.PrivateName == argName {
+ ifaceArg = arg
+ break
+ }
+ }
+
+ if ifaceArg == nil {
+ _, ok := objectArg.Type.(*NonNull)
+ err = invariant(
+ !ok,
+ fmt.Sprintf(`%v.%v(%v:) is of required type `+
+ `"%v" but is not also provided by the interface %v.%v.`,
+ object, fieldName, argName,
+ objectArg.Type, iface, fieldName),
+ )
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func isEqualType(typeA Type, typeB Type) bool {
+ // Equivalent type is a valid subtype
+ if typeA == typeB {
+ return true
+ }
+ // If either type is non-null, the other must also be non-null.
+ if typeA, ok := typeA.(*NonNull); ok {
+ if typeB, ok := typeB.(*NonNull); ok {
+ return isEqualType(typeA.OfType, typeB.OfType)
+ }
+ }
+ // If either type is a list, the other must also be a list.
+ if typeA, ok := typeA.(*List); ok {
+ if typeB, ok := typeB.(*List); ok {
+ return isEqualType(typeA.OfType, typeB.OfType)
+ }
+ }
+ // Otherwise the types are not equal.
+ return false
+}
+
+// isTypeSubTypeOf Provided a type and a super type, return true if the first type is either
+// equal or a subset of the second super type (covariant).
+func isTypeSubTypeOf(schema *Schema, maybeSubType Type, superType Type) bool {
+ // Equivalent type is a valid subtype
+ if maybeSubType == superType {
+ return true
+ }
+
+ // If superType is non-null, maybeSubType must also be nullable.
+ if superType, ok := superType.(*NonNull); ok {
+ if maybeSubType, ok := maybeSubType.(*NonNull); ok {
+ return isTypeSubTypeOf(schema, maybeSubType.OfType, superType.OfType)
+ }
+ return false
+ }
+ if maybeSubType, ok := maybeSubType.(*NonNull); ok {
+ // If superType is nullable, maybeSubType may be non-null.
+ return isTypeSubTypeOf(schema, maybeSubType.OfType, superType)
+ }
+
+ // If superType type is a list, maybeSubType type must also be a list.
+ if superType, ok := superType.(*List); ok {
+ if maybeSubType, ok := maybeSubType.(*List); ok {
+ return isTypeSubTypeOf(schema, maybeSubType.OfType, superType.OfType)
+ }
+ return false
+ } else if _, ok := maybeSubType.(*List); ok {
+ // If superType is not a list, maybeSubType must also be not a list.
+ return false
+ }
+
+ // If superType type is an abstract type, maybeSubType type may be a currently
+ // possible object type.
+ if superType, ok := superType.(*Interface); ok {
+ if maybeSubType, ok := maybeSubType.(*Object); ok && schema.IsPossibleType(superType, maybeSubType) {
+ return true
+ }
+ }
+ if superType, ok := superType.(*Union); ok {
+ if maybeSubType, ok := maybeSubType.(*Object); ok && schema.IsPossibleType(superType, maybeSubType) {
+ return true
+ }
+ }
+
+ // Otherwise, the child type is not a valid subtype of the parent type.
+ return false
+}