Comments (5)
Hi @pyros2097
Thanks for bringing this up 👍🏻
Could help to share the expected error message if you would have run it against graphql-js
?
Thanks! Cheers!
from graphql.
Here are the 2 examples,
package main
import (
"encoding/json"
"github.com/chris-ramon/graphql-go"
"github.com/chris-ramon/graphql-go/types"
)
var UserType = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{
Name: "User",
Description: "A user",
Fields: types.GraphQLFieldConfigMap{
"id": &types.GraphQLFieldConfig{
Type: types.NewGraphQLNonNull(types.GraphQLInt),
},
"name": &types.GraphQLFieldConfig{
Type: types.GraphQLInt,
},
},
})
func main() {
Schema, err := types.NewGraphQLSchema(types.GraphQLSchemaConfig{
Query: types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{
Name: "AA",
Fields: types.GraphQLFieldConfigMap{
"user": &types.GraphQLFieldConfig{
Type: UserType,
Resolve: func(p types.GQLFRParams) interface{} {
return map[string]interface{}{"id": "hello", "name": "hello"}
},
},
},
}),
})
if err != nil {
panic(err.Error())
}
resultChannel := make(chan *types.GraphQLResult)
params := gql.GraphqlParams{
Schema: Schema,
RootObject: nil,
RequestString: "query Test { user { id name } }",
}
go gql.Graphql(params, resultChannel)
result, err := json.Marshal(<-resultChannel)
if err != nil {
panic(err.Error())
}
println(string(result))
}
import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLNonNull,
GraphQLList,
GraphQLBoolean,
GraphQLInt,
GraphQLFloat,
GraphQLEnumType,
GraphQLScalarType,
GraphQLInputObjectType,
GraphQLUnionType,
graphql
} from 'graphql'
import {
Kind
} from 'graphql/language'
import {
GraphQLError
} from 'graphql/error'
var UserType = new GraphQLObjectType({
name: 'User',
description: 'A typical user',
fields: {
id: {
type: new GraphQLNonNull(GraphQLString),
description: 'The id of the user'
},
name: {
type: new GraphQLNonNull(GraphQLInt),
description: 'The full name of the user'
},
}
})
var Schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
user: {
type: UserType,
resolve(user, args, root) {
return {
id: "test",
name: "test"
}
}
},
}
}),
})
graphql(Schema, 'query Test { user { id name } }')
.then((result) => {
console.log(result)
})
// Cannot return null for non-nullable field User.id.
// User Error: expected iterable, but did not find one.
It seems it even the graphql-js doesn't do any typechecking. We are actually porting the graphql-js backend which we wrote earlier to go and I seemed to recall this error when I was developing in js. So I'll dig into it more and see when and where this ocurred
from graphql.
Hi @pyros2097
Thanks for providing the examples 👍🏻
Just for completeness sake, I've ran the examples you provided and ran both in graphql-js and graphql-go for confirm the output. They are expected to give the same output.
First example:
In this example, id
field is defined as GraphQLInt but returns a String value, so it returns a null value.
(Related gist: https://gist.github.com/sogko/a47c71711ed486dad15a)
Both graphql-js and graphql-go returned the same output.
{ data: { user: { id: null } } }
Second example
Both graphql-js and graphql-go returned the same output.
{ data: { user: { id: 'test', name: null } } }
Third example
Both graphql-js and graphql-go returned the same error in the output:
{ data: { user: null },
errors:
[ { [Error: Cannot return null for non-nullable field User.name.]
message: 'Cannot return null for non-nullable field User.name.' } ] }
Note: Neither should return User Error: expected iterable, but did not find one.
since none of the fields are defined with GraphQLList.
It seems it even the graphql-js doesn't do any typechecking.
Actually all the above are the expected behaviour.
- As per spec: Types are nullable by default.
- Resolving field with an error (for e.g. returning the wrong value type) will set the field to null. (See the tests in
executor/nonnull_test.go
, though there isn't a specific test for that but it is implied. We could add that to the test suite) - For example 1 and 2, since both fields are nullable, returning the wrong type will set them to null and no errors are returned.
- For example 3, the
name
field is defined as non-nullable Int but the resolve function returns a string.- This sets the field to null, which violates the defined schema, hence the
Cannot return null for non-nullable field User.name.
error message.
- This sets the field to null, which violates the defined schema, hence the
If you want to enforce strict type-checking for return type, I suggest taking advantage of Go for that.
Taking your example:
package main
import (
"encoding/json"
"github.com/chris-ramon/graphql-go"
"github.com/chris-ramon/graphql-go/types"
)
// Define a Go struct
// Note the `json` tags maps to the GraphQL field names,
// for e.g User.ID => `json:"id"`
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
var UserType = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{
Name: "User",
Description: "A typical user",
Fields: types.GraphQLFieldConfigMap{
"id": &types.GraphQLFieldConfig{
Type: types.NewGraphQLNonNull(types.GraphQLInt),
},
"name": &types.GraphQLFieldConfig{
Type: types.NewGraphQLNonNull(types.GraphQLString),
},
},
})
func main() {
Schema, err := types.NewGraphQLSchema(types.GraphQLSchemaConfig{
Query: types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{
Name: "Query",
Fields: types.GraphQLFieldConfigMap{
"user": &types.GraphQLFieldConfig{
Type: UserType,
Resolve: func(p types.GQLFRParams) interface{} {
// return `User` struct instead of `map[string]interface{}` for compile-time type-checking
return &User{
ID: 1, // there's no room for anyone to mistakenly return a string for ID field
Name: "Hello",
}
},
},
},
}),
})
...
}
// output:
{"data":{"user":{"id":1,"name":"Hello"}}}
Notes
- for
user
field, we return theUser
struct we defined, instead of usingmap[string]interface{}
- Each field type in the
User
struct maps to the type defined in the GraphQL schema.- For example
User.ID int
=>UserType.Fields.id.Type = GraphQLInt
- For example
- Take note that we use
json tags
in theUser
struct to map each field to the corresponding GraphQL field.
Let me know what you think!
from graphql.
Hi @sogko,
Thanks for your input. Its seems you did a lot of research into this. Yeah you are exactly right this is how it works according to the spec. But Still need to test out various features like custom scalars and check if they also validate with graphql-js.
There are still some parts in graphql-go that doesn't seem to work like graphql-js. I will open other issues for that and will thoroughly test it against graphql-js because we will be using it in out production app.
from graphql.
@pyros2097 Do share with us if you find disparity in behaviour between graphql-go
and graphql-js
👍🏻
Closing this issue.
Feel free to re-open if you feel that your concern has not been addressed.
from graphql.
Related Issues (20)
- New release?
- Potential goroutine leak in TestContextDeadline HOT 1
- Enums with trailing white space cause error.
- Playground
- make union input type ? it just have output union type
- With fiber HOT 1
- Printing GraphQL documents is slow HOT 1
- Bug with underscore and same name in keys from json response
- MongoDB _id field
- Printer returns invalid SDL if Block String comment contains double-quote
- When using custom scalar types, it's crucial to provide error feedback to users when issues arise with their submitted data. However, triggering exceptions within the ParseValue and ParseLiteral methods can lead to program crashes when using the graphql.Do method. This prevents the necessary error messages from being delivered to users.
- String type no longer recongised HOT 1
- Is it possible to go from `*graphql.Schema` to an ast node? HOT 1
- Error handling HOT 1
- Disabling Field Suggestions
- Is possible to typing typeConfig of graphql.Object after Object done.
- RootObjectFn request body always empty
- Unable to pass {{....}} as part of query or mutation string
- Redefining scalar ID
- How to support scalar JSON type? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from graphql.