Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
bd370d7
added subscribe support
branden-blackline Jul 14, 2019
e96c7c7
removing ordered fields code to keep PRs separate
branden-blackline Jul 14, 2019
a8d0d00
adding waitgroups to handle race
branden-blackline Jul 15, 2019
9cf0da7
Updating ResultIterator api and adding doneFunc per handler
branden-blackline Jul 16, 2019
4a374e3
ensure subscribe and resolve use the same cancellable context
branden-blackline Aug 18, 2019
8651f19
treat encoding.TextMarshaler as String
jekiapp Aug 21, 2019
ec949b3
switching from mutex to waitgroups and adding a subscriber type with …
branden-blackline Sep 11, 2019
08de84d
Merge branch 'master' into subscription-execution
bhoriuchi Dec 2, 2019
d6ffa49
Merge branch 'master' into subscription-execution
bhoriuchi Mar 9, 2020
f21d0c7
removing ResultIterator in favor of a result channel
branden-blackline May 17, 2020
a55996a
Merge branch 'master' into subscription-execution
bhoriuchi May 17, 2020
c991585
rewritten function signature and more tests
remorses May 18, 2020
ccd052d
initial tests pass
remorses May 18, 2020
7e815e2
added test for subscriptions parse errors
remorses May 18, 2020
2b63a00
handle errors in ExecuteSubscribe
remorses May 18, 2020
6baca7e
subscription: more tests cases
remorses May 18, 2020
a673078
subscription_test: refactored tests
remorses May 18, 2020
d55e8cb
subscription: removed some todos
remorses May 18, 2020
4e255bf
removed todos and prints
remorses May 18, 2020
1fc61f7
subscription: added more comments
remorses May 18, 2020
183515e
subscription: SubscriptableSchema conforms to ws interface
remorses May 18, 2020
77ab10b
subscription: added loop in subscriptabel schema
remorses May 18, 2020
ab87417
subscription: removed a print
remorses May 19, 2020
b63505c
subscription_test: added more tests for resolver behaviour
remorses May 19, 2020
3b13576
subscription_test: test for `panic inside subscribe is recovered`
remorses May 19, 2020
44a2828
subscription: added a comment
remorses May 19, 2020
eb0fdae
subscription: removed SubscriptableSchema
remorses May 19, 2020
d0a91ba
subscription: removed a print
remorses May 19, 2020
fd2a748
Merge pull request #1 from remorses/subscription-execution
bhoriuchi May 19, 2020
d54fb02
adding context cancel back to pass CI tests
branden-blackline May 19, 2020
7858706
Merge branch 'master' into subscription-execution
bhoriuchi Jul 1, 2020
3846be5
fix: error detection
CxdInitial Aug 3, 2020
4452f5e
Merge branch 'master' into improve_bindfields
chris-ramon Aug 15, 2020
33f0862
Merge pull request #503 from jekiapp/improve_bindfields
chris-ramon Aug 15, 2020
30eae24
Merge branch 'master' into patch-1
chris-ramon Aug 17, 2020
d6b7434
Merge pull request #561 from CxdInitial/patch-1
chris-ramon Aug 17, 2020
7fe5fa1
Merge branch 'master' into subscription-execution
bhoriuchi Aug 20, 2020
f7f76d6
examples/sql-nullstring: fix dropped error
alrs Sep 12, 2020
279aceb
examples/todo: extracts schema
chris-ramon Oct 10, 2020
05c348c
Merge pull request #574 from graphql-go/examples-todo-schema
chris-ramon Oct 11, 2020
cb98aa4
examples: adds http-post example
maapteh Oct 8, 2020
089f1ba
examples/http-post: fixes 'newline redundant' validation
chris-ramon Oct 11, 2020
dd05d5e
Merge pull request #575 from graphql-go/examples-http-post
chris-ramon Oct 11, 2020
5758832
Merge branch 'master' into subscription-execution
bhoriuchi Oct 14, 2020
5088e2a
Merge branch 'master' into fix-example-err
alrs Oct 21, 2020
ba29b76
Merge pull request #569 from alrs/fix-example-err
chris-ramon Nov 22, 2020
88c3051
Merge branch 'master' into subscription-execution
bhoriuchi Nov 23, 2020
388f8a2
Fix quotation during printing StringValue node
pkosiec Dec 7, 2020
0f4df50
use "invariantf" for performance
TheScenery Dec 22, 2020
62a7bb0
Merge pull request #590 from TheScenery/master
chris-ramon Jan 2, 2021
41c33dc
Merge branch 'master' into fix-json-string-arg
chris-ramon Jan 2, 2021
fe5921f
Merge branch 'master' into subscription-execution
bhoriuchi Jan 4, 2021
0f7ec2a
Updated the link to the latest pkg.go.dev
ujjwal-kr Jan 7, 2021
2a54235
Merge pull request #591 from ujjwal-kr/master
chris-ramon Jan 30, 2021
40d1ca7
README: updates go doc badge
chris-ramon Jan 30, 2021
0770b96
Merge branch 'master' into subscription-execution
chris-ramon Jan 31, 2021
1a9db88
Merge pull request #593 from graphql-go/README-pkg-go-dev-badge-update
chris-ramon Feb 7, 2021
4ce4c9a
Merge branch 'master' into subscription-execution
bhoriuchi Feb 24, 2021
18f6ed0
Merge branch 'master' into fix-json-string-arg
chris-ramon Apr 11, 2021
8a92e97
Merge pull request #587 from pkosiec/fix-json-string-arg
chris-ramon Apr 11, 2021
f51a3a2
Merge branch 'master' into subscription-execution
bhoriuchi Apr 11, 2021
f02a1c9
Merge pull request #495 from bhoriuchi/subscription-execution
chris-ramon Aug 21, 2021
0e40a4e
Support thunks for Union.Types definitions
alex-lange Jan 14, 2022
a300a61
Merge pull request #622 from alex-lange/lange-add-union-thunk
chris-ramon Jun 12, 2022
bdd0ee3
Adds Union.Types definition error handling unit test
chris-ramon Jun 12, 2022
09272f3
Merge pull request #633 from graphql-go/union-types-test
chris-ramon Jun 14, 2022
4188bd5
Fix infinite recursion in type definition parser
Invizory Jul 29, 2022
ec07c50
fix String/Name methods on the List type
dariuszkuc Oct 17, 2022
fc6b16f
fix: return valid object description
dariuszkuc Oct 18, 2022
2ce8c8b
Expose ParseValue
victor-perov Mar 26, 2019
55311b1
Merge pull request #656 from victor-perov/victor/expose-ParseValue
chris-ramon Feb 25, 2023
e9c5c5f
Merge branch 'master' into fix_object_description
chris-ramon Feb 25, 2023
d264c4c
Merge pull request #653 from dariuszkuc/fix_object_description
chris-ramon Feb 25, 2023
c18e0b6
Merge branch 'master' into fix_list_name
chris-ramon Feb 25, 2023
623f886
Merge pull request #651 from dariuszkuc/fix_list_name
chris-ramon Feb 25, 2023
2a6e1ff
Merge branch 'master' into fix-infinite-recursion-in-parser
chris-ramon Apr 10, 2023
a974186
Merge pull request #642 from Invizory/fix-infinite-recursion-in-parser
chris-ramon Apr 10, 2023
f4d0f50
fix postData's operationName on http-post example
qustavo Jul 20, 2023
4ebf270
Merge pull request #673 from qustavo/patch-1
chris-ramon Jul 22, 2023
9680004
Further flush out ability to auto-bind to functions and types, includ…
alancnet Jul 28, 2020
c1a04fc
[Jobot] Simple rename
alancnet Jul 28, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ test_with_go_modules: &test_with_go_modules
- run: go vet ./...

test_without_go_modules: &test_without_go_modules
working_directory: /go/src/github.com/graphql-go/graphql
working_directory: /go/src/github.com/teamjobot/graphql
steps:
- checkout
- run: go get -v -t -d ./...
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This document is based on the [Node.js contribution guidelines](https://github.c

## Chat room

[![Join the chat at https://gitter.im/graphql-go/graphql](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/graphql-go/graphql?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join the chat at https://gitter.im/teamjobot/graphql](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/teamjobot/graphql?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

Feel free to participate in the chat room for informal discussions and queries.

Expand Down Expand Up @@ -55,8 +55,8 @@ The basics are as follows:
2. `go get` the upstream repo and set it up as the `upstream` remote and your own repo as the `origin` remote:

```bash
$ go get github.com/graphql-go/graphql
$ cd $GOPATH/src/github.com/graphql-go/graphql
$ go get github.com/teamjobot/graphql
$ cd $GOPATH/src/github.com/teamjobot/graphql
$ git remote rename origin upstream
$ git remote add origin git@github.com/YOUR_GITHUB_NAME/graphql
```
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# graphql [![CircleCI](https://circleci.com/gh/graphql-go/graphql/tree/master.svg?style=svg)](https://circleci.com/gh/graphql-go/graphql/tree/master) [![GoDoc](https://godoc.org/graphql.co/graphql?status.svg)](https://godoc.org/github.com/graphql-go/graphql) [![Coverage Status](https://coveralls.io/repos/github/graphql-go/graphql/badge.svg?branch=master)](https://coveralls.io/github/graphql-go/graphql?branch=master) [![Join the chat at https://gitter.im/graphql-go/graphql](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/graphql-go/graphql?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# graphql [![CircleCI](https://circleci.com/gh/teamjobot/graphql/tree/master.svg?style=svg)](https://circleci.com/gh/teamjobot/graphql/tree/master) [![Go Reference](https://pkg.go.dev/badge/github.com/teamjobot/graphql.svg)](https://pkg.go.dev/github.com/teamjobot/graphql) [![Coverage Status](https://coveralls.io/repos/github/teamjobot/graphql/badge.svg?branch=master)](https://coveralls.io/github/teamjobot/graphql?branch=master) [![Join the chat at https://gitter.im/teamjobot/graphql](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/teamjobot/graphql?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

An implementation of GraphQL in Go. Follows the official reference implementation [`graphql-js`](https://github.com/graphql/graphql-js).

Supports: queries, mutations & subscriptions.

### Documentation

godoc: https://godoc.org/github.com/graphql-go/graphql
godoc: https://pkg.go.dev/github.com/teamjobot/graphql

### Getting Started

To install the library, run:
```bash
go get github.com/graphql-go/graphql
go get github.com/teamjobot/graphql
```

The following is a simple example which defines a schema with a single `hello` string-type field and a `Resolve` method which returns the string `world`. A GraphQL query is performed against this schema with the resulting output printed in JSON format.
Expand All @@ -25,7 +25,7 @@ import (
"fmt"
"log"

"github.com/graphql-go/graphql"
"github.com/teamjobot/graphql"
)

func main() {
Expand Down Expand Up @@ -60,13 +60,13 @@ func main() {
fmt.Printf("%s \n", rJSON) // {"data":{"hello":"world"}}
}
```
For more complex examples, refer to the [examples/](https://github.com/graphql-go/graphql/tree/master/examples/) directory and [graphql_test.go](https://github.com/graphql-go/graphql/blob/master/graphql_test.go).
For more complex examples, refer to the [examples/](https://github.com/teamjobot/graphql/tree/master/examples/) directory and [graphql_test.go](https://github.com/teamjobot/graphql/blob/master/graphql_test.go).

### Third Party Libraries
| Name | Author | Description |
|:-------------:|:-------------:|:------------:|
| [graphql-go-handler](https://github.com/graphql-go/graphql-go-handler) | [Hafiz Ismail](https://github.com/sogko) | Middleware to handle GraphQL queries through HTTP requests. |
| [graphql-relay-go](https://github.com/graphql-go/graphql-relay-go) | [Hafiz Ismail](https://github.com/sogko) | Lib to construct a graphql-go server supporting react-relay. |
| [teamjobot-handler](https://github.com/teamjobot/teamjobot-handler) | [Hafiz Ismail](https://github.com/sogko) | Middleware to handle GraphQL queries through HTTP requests. |
| [graphql-relay-go](https://github.com/teamjobot/graphql-relay-go) | [Hafiz Ismail](https://github.com/sogko) | Lib to construct a teamjobot server supporting react-relay. |
| [golang-relay-starter-kit](https://github.com/sogko/golang-relay-starter-kit) | [Hafiz Ismail](https://github.com/sogko) | Barebones starting point for a Relay application with Golang GraphQL server. |
| [dataloader](https://github.com/nicksrandall/dataloader) | [Nick Randall](https://github.com/nicksrandall) | [DataLoader](https://github.com/facebook/dataloader) implementation in Go. |

Expand Down
8 changes: 4 additions & 4 deletions abstract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"reflect"
"testing"

"github.com/graphql-go/graphql"
"github.com/graphql-go/graphql/gqlerrors"
"github.com/graphql-go/graphql/language/location"
"github.com/graphql-go/graphql/testutil"
"github.com/teamjobot/graphql"
"github.com/teamjobot/graphql/gqlerrors"
"github.com/teamjobot/graphql/language/location"
"github.com/teamjobot/graphql/testutil"
)

type testDog struct {
Expand Down
2 changes: 1 addition & 1 deletion benchutil/list_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package benchutil
import (
"fmt"

"github.com/graphql-go/graphql"
"github.com/teamjobot/graphql"
)

type color struct {
Expand Down
2 changes: 1 addition & 1 deletion benchutil/wide_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package benchutil
import (
"fmt"

"github.com/graphql-go/graphql"
"github.com/teamjobot/graphql"
)

func WideSchemaWithXFieldsAndYItems(x int, y int) graphql.Schema {
Expand Down
251 changes: 251 additions & 0 deletions bind.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
package graphql

import (
"context"
"encoding/json"
"fmt"
"reflect"
)

var ctxType = reflect.TypeOf((*context.Context)(nil)).Elem()
var errType = reflect.TypeOf((*error)(nil)).Elem()

/*
Bind will create a Field around a function formatted a certain way, or any value.

The input parameters can be, in any order,
- context.Context, or *context.Context (optional)
- An input struct, or pointer (optional)

The output parameters can be, in any order,
- A primitive, an output struct, or pointer (required for use in schema)
- error (optional)

Input or output types provided will be automatically bound using BindType.
*/
func Bind(bindTo interface{}, additionalFields ...Fields) *Field {
combinedAdditionalFields := MergeFields(additionalFields...)
val := reflect.ValueOf(bindTo)
tipe := reflect.TypeOf(bindTo)
if tipe.Kind() == reflect.Func {
in := tipe.NumIn()
out := tipe.NumOut()

var ctxIn *int
var inputIn *int

var errOut *int
var outputOut *int

queryArgs := FieldConfigArgument{}

if in > 2 {
panic(fmt.Sprintf("Mismatch on number of inputs. Expected 0, 1, or 2. got %d.", tipe.NumIn()))
}

if out > 2 {
panic(fmt.Sprintf("Mismatch on number of outputs. Expected 0, 1, or 2, got %d.", tipe.NumOut()))
}

// inTypes := make([]reflect.Type, in)
// outTypes := make([]reflect.Type, out)

for i := 0; i < in; i++ {
t := tipe.In(i)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
switch t {
case ctxType:
if ctxIn != nil {
panic(fmt.Sprintf("Unexpected multiple *context.Context inputs."))
}
ctxIn = intP(i)
default:
if inputIn != nil {
panic(fmt.Sprintf("Unexpected multiple inputs."))
}
inputType := tipe.In(i)
if inputType.Kind() == reflect.Ptr {
inputType = inputType.Elem()
}
inputFields := BindFields(reflect.New(inputType).Interface())
for key, inputField := range inputFields {
queryArgs[key] = &ArgumentConfig{
Type: inputField.Type,
}
}

inputIn = intP(i)
}
}

for i := 0; i < out; i++ {
t := tipe.Out(i)
switch t.String() {
case errType.String():
if errOut != nil {
panic(fmt.Sprintf("Unexpected multiple error outputs"))
}
errOut = intP(i)
default:
if outputOut != nil {
panic(fmt.Sprintf("Unexpected multiple outputs"))
}
outputOut = intP(i)
}
}

resolve := func(p ResolveParams) (output interface{}, err error) {
inputs := make([]reflect.Value, in)
if ctxIn != nil {
isPtr := tipe.In(*ctxIn).Kind() == reflect.Ptr
if isPtr {
if p.Context == nil {
inputs[*ctxIn] = reflect.New(ctxType)
} else {
inputs[*ctxIn] = reflect.ValueOf(&p.Context)
}
} else {
if p.Context == nil {
inputs[*ctxIn] = reflect.New(ctxType).Elem()
} else {
inputs[*ctxIn] = reflect.ValueOf(p.Context).Convert(ctxType).Elem()
}
}
}
if inputIn != nil {
var inputType, inputBaseType, sourceType, sourceBaseType reflect.Type
sourceVal := reflect.ValueOf(p.Source)
sourceExists := !sourceVal.IsZero()
if sourceExists {
sourceType = sourceVal.Type()
if sourceType.Kind() == reflect.Ptr {
sourceBaseType = sourceType.Elem()
} else {
sourceBaseType = sourceType
}
}
inputType = tipe.In(*inputIn)
isPtr := tipe.In(*inputIn).Kind() == reflect.Ptr
if isPtr {
inputBaseType = inputType.Elem()
} else {
inputBaseType = inputType
}
var input interface{}
if sourceExists && sourceBaseType.AssignableTo(inputBaseType) {
input = sourceVal.Interface()
} else {
input = reflect.New(inputBaseType).Interface()
j, err := json.Marshal(p.Args)
if err == nil {
err = json.Unmarshal(j, &input)
}
if err != nil {
return nil, err
}
}

inputs[*inputIn], err = convertValue(reflect.ValueOf(input), inputType)
if err != nil {
return nil, err
}
}
results := val.Call(inputs)
if errOut != nil {
val := results[*errOut].Interface()
if val != nil {
err = val.(error)
}
if err != nil {
return output, err
}
}
if outputOut != nil {
var val reflect.Value
val, err = convertValue(results[*outputOut], tipe.Out(*outputOut))
if err != nil {
return nil, err
}
if !val.IsZero() {
output = val.Interface()
}
}
return output, err
}

var outputType Output
if outputOut != nil {
outputType = BindType(tipe.Out(*outputOut))
extendType(outputType, combinedAdditionalFields)
}

field := &Field{
Type: outputType,
Resolve: resolve,
Args: queryArgs,
}

return field
} else if tipe.Kind() == reflect.Struct {
fieldType := BindType(reflect.TypeOf(bindTo))
extendType(fieldType, combinedAdditionalFields)
field := &Field{
Type: fieldType,
Resolve: func(p ResolveParams) (data interface{}, err error) {
return bindTo, nil
},
}
return field
} else {
if len(additionalFields) > 0 {
panic("Cannot add field resolvers to a scalar type.")
}
return &Field{
Type: getGraphType(tipe),
Resolve: func(p ResolveParams) (data interface{}, err error) {
return bindTo, nil
},
}
}
}

func extendType(t Type, fields Fields) {
switch t.(type) {
case *Object:
object := t.(*Object)
for fieldName, fieldConfig := range fields {
object.AddFieldConfig(fieldName, fieldConfig)
}
return
case *List:
list := t.(*List)
extendType(list.OfType, fields)
return
}
}

func convertValue(value reflect.Value, targetType reflect.Type) (ret reflect.Value, err error) {
if !value.IsValid() || value.IsZero() {
return reflect.Zero(targetType), nil
}
if value.Type().Kind() == reflect.Ptr {
if targetType.Kind() == reflect.Ptr {
return value, nil
} else {
return value.Elem(), nil
}
} else {
if targetType.Kind() == reflect.Ptr {
// Will throw an informative error
return value.Convert(targetType), nil
} else {
return value, nil
}
}
}

func intP(i int) *int {
return &i
}
Loading