diff options
Diffstat (limited to 'vendor/github.com/vektah/gqlparser/validator/schema.go')
-rw-r--r-- | vendor/github.com/vektah/gqlparser/validator/schema.go | 94 |
1 files changed, 79 insertions, 15 deletions
diff --git a/vendor/github.com/vektah/gqlparser/validator/schema.go b/vendor/github.com/vektah/gqlparser/validator/schema.go index 8fa18d7e..57d2022e 100644 --- a/vendor/github.com/vektah/gqlparser/validator/schema.go +++ b/vendor/github.com/vektah/gqlparser/validator/schema.go @@ -4,6 +4,7 @@ package validator import ( "strconv" + "strings" . "github.com/vektah/gqlparser/ast" "github.com/vektah/gqlparser/gqlerror" @@ -11,20 +12,19 @@ import ( ) 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) + ast, err := parser.ParseSchemas(inputs...) + if err != nil { + return nil, err } + return ValidateSchemaDocument(ast) +} +func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, *gqlerror.Error) { schema := Schema{ Types: map[string]*Definition{}, Directives: map[string]*DirectiveDefinition{}, PossibleTypes: map[string][]*Definition{}, + Implements: map[string][]*Definition{}, } for i, def := range ast.Definitions { @@ -32,13 +32,6 @@ func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) { 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 { @@ -58,6 +51,22 @@ func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) { def.EnumValues = append(def.EnumValues, ext.EnumValues...) } + for _, def := range ast.Definitions { + switch def.Kind { + case Union: + for _, t := range def.Types { + schema.AddPossibleType(def.Name, schema.Types[t]) + schema.AddImplements(t, def) + } + case InputObject, Object: + for _, intf := range def.Interfaces { + schema.AddPossibleType(intf, def) + schema.AddImplements(def.Name, schema.Types[intf]) + } + schema.AddPossibleType(def.Name, def) + } + } + for i, dir := range ast.Directives { if schema.Directives[dir.Name] != nil { return nil, gqlerror.ErrorPosf(dir.Position, "Cannot redeclare directive %s.", dir.Name) @@ -150,11 +159,20 @@ func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) { } func validateDirective(schema *Schema, def *DirectiveDefinition) *gqlerror.Error { + if err := validateName(def.Position, def.Name); err != nil { + // now, GraphQL spec doesn't have reserved directive name + return err + } + return validateArgs(schema, def.Arguments, def) } func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error { for _, field := range def.Fields { + if err := validateName(field.Position, field.Name); err != nil { + // now, GraphQL spec doesn't have reserved field name + return err + } if err := validateTypeRef(schema, field.Type); err != nil { return err } @@ -176,6 +194,37 @@ func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error { } } + switch def.Kind { + case Object, Interface: + if len(def.Fields) == 0 { + return gqlerror.ErrorPosf(def.Position, "%s must define one or more fields.", def.Kind) + } + case Enum: + if len(def.EnumValues) == 0 { + return gqlerror.ErrorPosf(def.Position, "%s must define one or more unique enum values.", def.Kind) + } + case InputObject: + if len(def.Fields) == 0 { + return gqlerror.ErrorPosf(def.Position, "%s must define one or more input fields.", def.Kind) + } + } + + for idx, field1 := range def.Fields { + for _, field2 := range def.Fields[idx+1:] { + if field1.Name == field2.Name { + return gqlerror.ErrorPosf(field2.Position, "Field %s.%s can only be defined once.", def.Name, field2.Name) + } + } + } + + if !def.BuiltIn { + // GraphQL spec has reserved type names a lot! + err := validateName(def.Position, def.Name) + if err != nil { + return err + } + } + return validateDirectives(schema, def.Directives, nil) } @@ -188,6 +237,10 @@ func validateTypeRef(schema *Schema, typ *Type) *gqlerror.Error { func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective *DirectiveDefinition) *gqlerror.Error { for _, arg := range args { + if err := validateName(arg.Position, arg.Name); err != nil { + // now, GraphQL spec doesn't have reserved argument name + return err + } if err := validateTypeRef(schema, arg.Type); err != nil { return err } @@ -200,6 +253,10 @@ func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective func validateDirectives(schema *Schema, dirs DirectiveList, currentDirective *DirectiveDefinition) *gqlerror.Error { for _, dir := range dirs { + if err := validateName(dir.Position, dir.Name); err != nil { + // now, GraphQL spec doesn't have reserved directive name + return err + } if currentDirective != nil && dir.Name == currentDirective.Name { return gqlerror.ErrorPosf(dir.Position, "Directive %s cannot refer to itself.", currentDirective.Name) } @@ -210,3 +267,10 @@ func validateDirectives(schema *Schema, dirs DirectiveList, currentDirective *Di } return nil } + +func validateName(pos *Position, name string) *gqlerror.Error { + if strings.HasPrefix(name, "__") { + return gqlerror.ErrorPosf(pos, `Name "%s" must not begin with "__", which is reserved by GraphQL introspection.`, name) + } + return nil +} |