Skip to content

Commit

Permalink
Allow directives on schema (graph-gophers#585)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelnikolov authored and KNiepok committed Feb 28, 2023
1 parent 7ddb8a6 commit 25e8656
Show file tree
Hide file tree
Showing 4 changed files with 341 additions and 15 deletions.
79 changes: 67 additions & 12 deletions ast/schema.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ast

import "github.com/graph-gophers/graphql-go/errors"

// Schema represents a GraphQL service's collective type system capabilities.
// A schema is defined in terms of the types and directives it supports as well as the root
// operation types for each kind of operation: `query`, `mutation`, and `subscription`.
Expand All @@ -8,12 +10,8 @@ package ast
//
// http://spec.graphql.org/draft/#sec-Schema
type Schema struct {
// RootOperationTypes determines the place in the type system where `query`, `mutation`, and
// `subscription` operations begin.
//
// http://spec.graphql.org/draft/#sec-Root-Operation-Types
//
RootOperationTypes map[string]NamedType
// SchemaDefinition corresponds to the `schema` sdl keyword.
SchemaDefinition

// Types are the fundamental unit of any GraphQL schema.
// There are six kinds of named type definitions in GraphQL, and two wrapping types.
Expand All @@ -28,14 +26,71 @@ type Schema struct {
// http://spec.graphql.org/#sec-Type-System.Directives
Directives map[string]*DirectiveDefinition

EntryPointNames map[string]string
Objects []*ObjectTypeDefinition
Unions []*Union
Enums []*EnumTypeDefinition
Extensions []*Extension
SchemaString string
Objects []*ObjectTypeDefinition
Unions []*Union
Enums []*EnumTypeDefinition
Extensions []*Extension
SchemaString string
}

func (s *Schema) Resolve(name string) Type {
return s.Types[name]
}

// SchemaDefinition is an optional schema block.
// If the schema definition is present it might contain a description and directives. It also contains a map of root operations. For example:
//
// schema {
// query: Query
// mutation: Mutation
// subscription: Subscription
// }
//
// type Query {
// # query fields go here
// }
//
// type Mutation {
// # mutation fields go here
// }
//
// type Subscription {
// # subscription fields go here
// }
//
// If the root operations have default names (i.e. Query, Mutation and Subscription), then the schema definition can be omitted. For example, this is equivalent to the above schema:
//
// type Query {
// # query fields go here
// }
//
// type Mutation {
// # mutation fields go here
// }
//
// type Subscription {
// # subscription fields go here
// }
//
// https://spec.graphql.org/October2021/#sec-Schema
type SchemaDefinition struct {
// Present is true if the schema definition is not omitted, false otherwise. For example, in the following schema
//
// type Query {
// hello: String!
// }
//
// the schema keyword is omitted since the default name for Query is used. In that case Present would be false.
Present bool

// RootOperationTypes determines the place in the type system where `query`, `mutation`, and
// `subscription` operations begin.
//
// http://spec.graphql.org/draft/#sec-Root-Operation-Types
RootOperationTypes map[string]NamedType

EntryPointNames map[string]string
Desc string
Directives DirectiveList
Loc errors.Location
}
2 changes: 2 additions & 0 deletions examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ func (s Season) String() string {
panic("unreachable")
}
`

funcs := template.FuncMap{
"toVar": func(s string) string {
if len(s) == 0 {
Expand All @@ -300,6 +301,7 @@ func (s Season) String() string {
return strings.ToUpper(s[:1]) + strings.ToLower(s[1:])
},
}

tpl, err := template.New("enum").Funcs(funcs).Parse(gocode)
if err != nil {
panic(err)
Expand Down
14 changes: 11 additions & 3 deletions internal/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import (
// New initializes an instance of Schema.
func New() *ast.Schema {
s := &ast.Schema{
EntryPointNames: make(map[string]string),
Types: make(map[string]ast.NamedType),
Directives: make(map[string]*ast.DirectiveDefinition),
SchemaDefinition: ast.SchemaDefinition{
EntryPointNames: make(map[string]string),
},
Types: make(map[string]ast.NamedType),
Directives: make(map[string]*ast.DirectiveDefinition),
}
m := newMeta()
for n, t := range m.Types {
Expand Down Expand Up @@ -362,6 +364,10 @@ func parseSchema(s *ast.Schema, l *common.Lexer) {
switch x := l.ConsumeIdent(); x {

case "schema":
s.SchemaDefinition.Present = true
s.SchemaDefinition.Loc = l.Location()
s.SchemaDefinition.Desc = desc
s.SchemaDefinition.Directives = common.ParseDirectives(l)
l.ConsumeToken('{')
for l.Peek() != '}' {

Expand Down Expand Up @@ -565,6 +571,8 @@ func parseExtension(s *ast.Schema, l *common.Lexer) {
switch x := l.ConsumeIdent(); x {
case "schema":
l.ConsumeToken('{')
s.SchemaDefinition.Present = true
s.SchemaDefinition.Directives = append(s.SchemaDefinition.Directives, common.ParseDirectives(l)...)
for l.Peek() != '}' {
name := l.ConsumeIdent()
l.ConsumeToken(':')
Expand Down
Loading

0 comments on commit 25e8656

Please sign in to comment.