aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/vektah/gqlparser/validator/schema.go
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-09-14 12:40:31 +0200
committerMichael Muré <batolettre@gmail.com>2018-09-14 12:41:59 +0200
commitb478cd1bcb4756b20f7f4b15fcf81f23e1a60a02 (patch)
tree8ce232dcab3dd00708f8ba66c334472457e5980d /vendor/github.com/vektah/gqlparser/validator/schema.go
parenta3fc9abb921f5ce7084d6ab7473442d0b72b1d78 (diff)
downloadgit-bug-b478cd1bcb4756b20f7f4b15fcf81f23e1a60a02.tar.gz
graphql: update gqlgen to 0.5.1
fix #6
Diffstat (limited to 'vendor/github.com/vektah/gqlparser/validator/schema.go')
-rw-r--r--vendor/github.com/vektah/gqlparser/validator/schema.go212
1 files changed, 212 insertions, 0 deletions
diff --git a/vendor/github.com/vektah/gqlparser/validator/schema.go b/vendor/github.com/vektah/gqlparser/validator/schema.go
new file mode 100644
index 00000000..8fa18d7e
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/validator/schema.go
@@ -0,0 +1,212 @@
+//go:generate go run ./inliner/inliner.go
+
+package validator
+
+import (
+ "strconv"
+
+ . "github.com/vektah/gqlparser/ast"
+ "github.com/vektah/gqlparser/gqlerror"
+ "github.com/vektah/gqlparser/parser"
+)
+
+func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) {
+ ast := &SchemaDocument{}
+ for _, input := range inputs {
+ inputAst, err := parser.ParseSchema(input)
+ if err != nil {
+ return nil, err
+ }
+
+ ast.Merge(inputAst)
+ }
+
+ schema := Schema{
+ Types: map[string]*Definition{},
+ Directives: map[string]*DirectiveDefinition{},
+ PossibleTypes: map[string][]*Definition{},
+ }
+
+ for i, def := range ast.Definitions {
+ if schema.Types[def.Name] != nil {
+ return nil, gqlerror.ErrorPosf(def.Position, "Cannot redeclare type %s.", def.Name)
+ }
+ schema.Types[def.Name] = ast.Definitions[i]
+
+ if def.Kind != Interface {
+ for _, intf := range def.Interfaces {
+ schema.AddPossibleType(intf, ast.Definitions[i])
+ }
+ schema.AddPossibleType(def.Name, ast.Definitions[i])
+ }
+ }
+
+ for _, ext := range ast.Extensions {
+ def := schema.Types[ext.Name]
+ if def == nil {
+ return nil, gqlerror.ErrorPosf(ext.Position, "Cannot extend type %s because it does not exist.", ext.Name)
+ }
+
+ if def.Kind != ext.Kind {
+ return nil, gqlerror.ErrorPosf(ext.Position, "Cannot extend type %s because the base type is a %s, not %s.", ext.Name, def.Kind, ext.Kind)
+ }
+
+ def.Directives = append(def.Directives, ext.Directives...)
+ def.Interfaces = append(def.Interfaces, ext.Interfaces...)
+ def.Fields = append(def.Fields, ext.Fields...)
+ def.Types = append(def.Types, ext.Types...)
+ def.EnumValues = append(def.EnumValues, ext.EnumValues...)
+ }
+
+ for i, dir := range ast.Directives {
+ if schema.Directives[dir.Name] != nil {
+ return nil, gqlerror.ErrorPosf(dir.Position, "Cannot redeclare directive %s.", dir.Name)
+ }
+ schema.Directives[dir.Name] = ast.Directives[i]
+ }
+
+ if len(ast.Schema) > 1 {
+ return nil, gqlerror.ErrorPosf(ast.Schema[1].Position, "Cannot have multiple schema entry points, consider schema extensions instead.")
+ }
+
+ if len(ast.Schema) == 1 {
+ for _, entrypoint := range ast.Schema[0].OperationTypes {
+ def := schema.Types[entrypoint.Type]
+ if def == nil {
+ return nil, gqlerror.ErrorPosf(entrypoint.Position, "Schema root %s refers to a type %s that does not exist.", entrypoint.Operation, entrypoint.Type)
+ }
+ switch entrypoint.Operation {
+ case Query:
+ schema.Query = def
+ case Mutation:
+ schema.Mutation = def
+ case Subscription:
+ schema.Subscription = def
+ }
+ }
+ }
+
+ for _, ext := range ast.SchemaExtension {
+ for _, entrypoint := range ext.OperationTypes {
+ def := schema.Types[entrypoint.Type]
+ if def == nil {
+ return nil, gqlerror.ErrorPosf(entrypoint.Position, "Schema root %s refers to a type %s that does not exist.", entrypoint.Operation, entrypoint.Type)
+ }
+ switch entrypoint.Operation {
+ case Query:
+ schema.Query = def
+ case Mutation:
+ schema.Mutation = def
+ case Subscription:
+ schema.Subscription = def
+ }
+ }
+ }
+
+ for _, typ := range schema.Types {
+ err := validateDefinition(&schema, typ)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ for _, dir := range schema.Directives {
+ err := validateDirective(&schema, dir)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if schema.Query == nil && schema.Types["Query"] != nil {
+ schema.Query = schema.Types["Query"]
+ }
+
+ if schema.Mutation == nil && schema.Types["Mutation"] != nil {
+ schema.Mutation = schema.Types["Mutation"]
+ }
+
+ if schema.Subscription == nil && schema.Types["Subscription"] != nil {
+ schema.Subscription = schema.Types["Subscription"]
+ }
+
+ if schema.Query != nil {
+ schema.Query.Fields = append(
+ schema.Query.Fields,
+ &FieldDefinition{
+ Name: "__schema",
+ Type: NonNullNamedType("__Schema", nil),
+ },
+ &FieldDefinition{
+ Name: "__type",
+ Type: NonNullNamedType("__Type", nil),
+ Arguments: ArgumentDefinitionList{
+ {Name: "name", Type: NamedType("String", nil)},
+ },
+ },
+ )
+ }
+
+ return &schema, nil
+}
+
+func validateDirective(schema *Schema, def *DirectiveDefinition) *gqlerror.Error {
+ return validateArgs(schema, def.Arguments, def)
+}
+
+func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error {
+ for _, field := range def.Fields {
+ if err := validateTypeRef(schema, field.Type); err != nil {
+ return err
+ }
+ if err := validateArgs(schema, field.Arguments, nil); err != nil {
+ return err
+ }
+ if err := validateDirectives(schema, field.Directives, nil); err != nil {
+ return err
+ }
+ }
+
+ for _, intf := range def.Interfaces {
+ intDef := schema.Types[intf]
+ if intDef == nil {
+ return gqlerror.ErrorPosf(def.Position, "Undefined type %s.", strconv.Quote(intf))
+ }
+ if intDef.Kind != Interface {
+ return gqlerror.ErrorPosf(def.Position, "%s is a non interface type %s.", strconv.Quote(intf), intDef.Kind)
+ }
+ }
+
+ return validateDirectives(schema, def.Directives, nil)
+}
+
+func validateTypeRef(schema *Schema, typ *Type) *gqlerror.Error {
+ if schema.Types[typ.Name()] == nil {
+ return gqlerror.ErrorPosf(typ.Position, "Undefined type %s.", typ.Name())
+ }
+ return nil
+}
+
+func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective *DirectiveDefinition) *gqlerror.Error {
+ for _, arg := range args {
+ if err := validateTypeRef(schema, arg.Type); err != nil {
+ return err
+ }
+ if err := validateDirectives(schema, arg.Directives, currentDirective); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func validateDirectives(schema *Schema, dirs DirectiveList, currentDirective *DirectiveDefinition) *gqlerror.Error {
+ for _, dir := range dirs {
+ if currentDirective != nil && dir.Name == currentDirective.Name {
+ return gqlerror.ErrorPosf(dir.Position, "Directive %s cannot refer to itself.", currentDirective.Name)
+ }
+ if schema.Directives[dir.Name] == nil {
+ return gqlerror.ErrorPosf(dir.Position, "Undefined directive %s.", dir.Name)
+ }
+ dir.Definition = schema.Directives[dir.Name]
+ }
+ return nil
+}