Skip to content

Commit

Permalink
Merge branch 'sogko/0.6.0' into sogko/experiment-parallel-resolve
Browse files Browse the repository at this point in the history
* sogko/0.6.0: (34 commits)
  gofmt -s
  executor: add graphql tag
  Fix ObjectConfig duplicate json tag. Name had a 'description' json tag which was duplicate
  Minor fix to stop `go vet` from complaining
  Add 1.7 and tip to build matrix for Go
  Minor fix to stop `go vet` from complaining
  README: add Documentation section
  Fixes tests that was broken with enhancements made to the `lexer` with commit #137
  Improve lexer performance by using a byte array as source
  Validation: improving overlapping fields quality (#386)
  Validation: context.getFragmentSpreads now accepts selectionSet rather than fragment AST node
  Factor out more closure functions
  Factor out closure functions to normal functions
  Deprecated directive (#384)
  Revert back directives to use `var`; `const` not applicable here
  Deprecated directive (#384)
  RFC: Directive location: schema definition (#382)
  RFC: Schema Language Directives (#376)
  Update `NewSchema()` to use new exported introspective types
  Export introspection in public API
  ...
  • Loading branch information
sogko committed Jan 27, 2017
2 parents 14fac79 + e13376c commit 0ba9e8f
Show file tree
Hide file tree
Showing 41 changed files with 2,727 additions and 1,127 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ language: go

go:
- 1.4
- 1.7
- tip

before_install:
- go get github.com/axw/gocov/gocov
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

A *work-in-progress* implementation of GraphQL for Go.

### Documentation

godoc: https://godoc.org/github.com/graphql-go/graphql

### Getting Started

To install the library, run:
Expand Down
5 changes: 4 additions & 1 deletion definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ 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)
Expand Down Expand Up @@ -389,7 +392,7 @@ type IsTypeOfFn func(p IsTypeOfParams) bool
type InterfacesThunk func() []*Interface

type ObjectConfig struct {
Name string `json:"description"`
Name string `json:"name"`
Interfaces interface{} `json:"interfaces"`
Fields interface{} `json:"fields"`
IsTypeOf IsTypeOfFn `json:"isTypeOf"`
Expand Down
47 changes: 45 additions & 2 deletions directives.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
package graphql

const (
// Operations
DirectiveLocationQuery = "QUERY"
DirectiveLocationMutation = "MUTATION"
DirectiveLocationSubscription = "SUBSCRIPTION"
DirectiveLocationField = "FIELD"
DirectiveLocationFragmentDefinition = "FRAGMENT_DEFINITION"
DirectiveLocationFragmentSpread = "FRAGMENT_SPREAD"
DirectiveLocationInlineFragment = "INLINE_FRAGMENT"

// Schema Definitions
DirectiveLocationSchema = "SCHEMA"
DirectiveLocationScalar = "SCALAR"
DirectiveLocationObject = "OBJECT"
DirectiveLocationFieldDefinition = "FIELD_DEFINITION"
DirectiveLocationArgumentDefinition = "ARGUMENT_DEFINITION"
DirectiveLocationInterface = "INTERFACE"
DirectiveLocationUnion = "UNION"
DirectiveLocationEnum = "ENUM"
DirectiveLocationEnumValue = "ENUM_VALUE"
DirectiveLocationInputObject = "INPUT_OBJECT"
DirectiveLocationInputFieldDefinition = "INPUT_FIELD_DEFINITION"
)

// DefaultDeprecationReason Constant string used for default reason for a deprecation.
const DefaultDeprecationReason = "No longer supported"

// SpecifiedRules The full list of specified directives.
var SpecifiedDirectives = []*Directive{
IncludeDirective,
SkipDirective,
DeprecatedDirective,
}

// Directive structs are used by the GraphQL runtime as a way of modifying execution
// behavior. Type system creators will usually not create these directly.
type Directive struct {
Expand Down Expand Up @@ -76,7 +100,7 @@ func NewDirective(config DirectiveConfig) *Directive {
return dir
}

// IncludeDirective is used to conditionally include fields or fragments
// IncludeDirective is used to conditionally include fields or fragments.
var IncludeDirective = NewDirective(DirectiveConfig{
Name: "include",
Description: "Directs the executor to include this field or fragment only when " +
Expand All @@ -94,7 +118,7 @@ var IncludeDirective = NewDirective(DirectiveConfig{
},
})

// SkipDirective Used to conditionally skip (exclude) fields or fragments
// SkipDirective Used to conditionally skip (exclude) fields or fragments.
var SkipDirective = NewDirective(DirectiveConfig{
Name: "skip",
Description: "Directs the executor to skip this field or fragment when the `if` " +
Expand All @@ -111,3 +135,22 @@ var SkipDirective = NewDirective(DirectiveConfig{
DirectiveLocationInlineFragment,
},
})

// DeprecatedDirective Used to declare element of a GraphQL schema as deprecated.
var DeprecatedDirective = NewDirective(DirectiveConfig{
Name: "deprecated",
Description: "Marks an element of a GraphQL schema as no longer supported.",
Args: FieldConfigArgument{
"reason": &ArgumentConfig{
Type: String,
Description: "Explains why this element was deprecated, usually also including a " +
"suggestion for how to access supported similar data. Formatted" +
"in [Markdown](https://daringfireball.net/projects/markdown/).",
DefaultValue: DefaultDeprecationReason,
},
},
Locations: []string{
DirectiveLocationFieldDefinition,
DirectiveLocationEnumValue,
},
})
12 changes: 0 additions & 12 deletions directives_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,6 @@ func TestDirectivesWorksOnInlineFragmentIfFalseOmitsInlineFragment(t *testing.T)
b
}
}
fragment Frag on TestType {
b
}
`
expected := &graphql.Result{
Data: map[string]interface{}{
Expand All @@ -368,9 +365,6 @@ func TestDirectivesWorksOnInlineFragmentIfTrueIncludesInlineFragment(t *testing.
b
}
}
fragment Frag on TestType {
b
}
`
expected := &graphql.Result{
Data: map[string]interface{}{
Expand All @@ -395,9 +389,6 @@ func TestDirectivesWorksOnInlineFragmentUnlessFalseIncludesInlineFragment(t *tes
b
}
}
fragment Frag on TestType {
b
}
`
expected := &graphql.Result{
Data: map[string]interface{}{
Expand All @@ -422,9 +413,6 @@ func TestDirectivesWorksOnInlineFragmentUnlessTrueIncludesInlineFragment(t *test
b
}
}
fragment Frag on TestType {
b
}
`
expected := &graphql.Result{
Data: map[string]interface{}{
Expand Down
27 changes: 16 additions & 11 deletions executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,9 @@ func completeAbstractValue(eCtx *ExecutionContext, returnType Abstract, fieldAST
}

err := invariant(runtimeType != nil,
fmt.Sprintf(`Could not determine runtime type of value "%v" for field %v.%v.`, result, info.ParentType, info.FieldName),
fmt.Sprintf(`Abstract type %v must resolve to an Object type at runtime `+
`for field %v.%v with value "%v", received "%v".`,
returnType, info.ParentType, info.FieldName, result, runtimeType),
)
if err != nil {
panic(err)
Expand Down Expand Up @@ -874,10 +876,6 @@ func defaultResolveFn(p ResolveParams) (interface{}, error) {
return nil, nil
}
if sourceVal.Type().Kind() == reflect.Struct {
// find field based on struct's json tag
// we could potentially create a custom `graphql` tag, but its unnecessary at this point
// since graphql speaks to client in a json-like way anyway
// so json tags are a good way to start with
for i := 0; i < sourceVal.NumField(); i++ {
valueField := sourceVal.Field(i)
typeField := sourceVal.Type().Field(i)
Expand All @@ -886,15 +884,22 @@ func defaultResolveFn(p ResolveParams) (interface{}, error) {
return valueField.Interface(), nil
}
tag := typeField.Tag
jsonTag := tag.Get("json")
jsonOptions := strings.Split(jsonTag, ",")
if len(jsonOptions) == 0 {
continue
checkTag := func(tagName string) bool {
t := tag.Get(tagName)
tOptions := strings.Split(t, ",")
if len(tOptions) == 0 {
return false
}
if tOptions[0] != p.Info.FieldName {
return false
}
return true
}
if jsonOptions[0] != p.Info.FieldName {
if checkTag("json") || checkTag("graphql") {
return valueField.Interface(), nil
} else {
continue
}
return valueField.Interface(), nil
}
return nil, nil
}
Expand Down
47 changes: 47 additions & 0 deletions executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1592,3 +1592,50 @@ func TestMutation_ExecutionDoesNotAddErrorsFromFieldResolveFn(t *testing.T) {
t.Fatalf("wrong result, unexpected errors: %+v", result.Errors)
}
}

func TestGraphqlTag(t *testing.T) {
typeObjectType := graphql.NewObject(graphql.ObjectConfig{
Name: "Type",
Fields: graphql.Fields{
"fooBar": &graphql.Field{Type: graphql.String},
},
})
var baz = &graphql.Field{
Type: typeObjectType,
Description: "typeObjectType",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
t := struct {
FooBar string `graphql:"fooBar"`
}{"foo bar value"}
return t, nil
},
}
q := graphql.NewObject(graphql.ObjectConfig{
Name: "Query",
Fields: graphql.Fields{
"baz": baz,
},
})
schema, err := graphql.NewSchema(graphql.SchemaConfig{
Query: q,
})
if err != nil {
t.Fatalf("unexpected error, got: %v", err)
}
query := "{ baz { fooBar } }"
result := graphql.Do(graphql.Params{
Schema: schema,
RequestString: query,
})
if len(result.Errors) != 0 {
t.Fatalf("wrong result, unexpected errors: %+v", result.Errors)
}
expectedData := map[string]interface{}{
"baz": map[string]interface{}{
"fooBar": "foo bar value",
},
}
if !reflect.DeepEqual(result.Data, expectedData) {
t.Fatalf("unexpected result, got: %+v, expected: %+v", expectedData, result.Data)
}
}
4 changes: 2 additions & 2 deletions gqlerrors/syntax.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package gqlerrors
import (
"fmt"
"regexp"
"strings"

"github.com/graphql-go/graphql/language/ast"
"github.com/graphql-go/graphql/language/location"
"github.com/graphql-go/graphql/language/source"
"strings"
)

func NewSyntaxError(s *source.Source, position int, description string) *Error {
Expand Down Expand Up @@ -44,7 +44,7 @@ func highlightSourceAtLocation(s *source.Source, l location.SourceLocation) stri
lineNum := fmt.Sprintf("%d", line)
nextLineNum := fmt.Sprintf("%d", (line + 1))
padLen := len(nextLineNum)
lines := regexp.MustCompile("\r\n|[\n\r]").Split(s.Body, -1)
lines := regexp.MustCompile("\r\n|[\n\r]").Split(string(s.Body), -1)
var highlight string
if line >= 2 {
highlight += fmt.Sprintf("%s: %s\n", lpad(padLen, prevLineNum), printLine(lines[line-2]))
Expand Down
2 changes: 1 addition & 1 deletion graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type Params struct {

func Do(p Params) *Result {
source := source.NewSource(&source.Source{
Body: p.RequestString,
Body: []byte(p.RequestString),
Name: "GraphQL request",
})
AST, err := parser.Parse(parser.ParseParams{Source: source})
Expand Down
Loading

0 comments on commit 0ba9e8f

Please sign in to comment.