Comments (3)
Closing issue since there was no comment in more than 3 years.
from graphql.
Hi @pyros2097
I just got around to take a look into this now that we've gotten the major API change out of the way 😃
Hmm, to start with, I think there is a mismatch between what you have defined as the OutputField
and the actual value that you return in MutateAndGetPayload
.
Also, the above uses the relay
library, which I think confuses most people who are not familiar with Relay (which is not part of GraphQL spec, but rather a separate "extension" that adds other stuff to it (i.e. global ID, pagination helpers etc)
I've re-written your example with pure GraphQL and using the new API.
package main
import (
"errors"
"github.com/graphql-go/graphql"
"github.com/graphql-go/graphql/language/ast"
"github.com/graphql-go/graphql/language/kinds"
"github.com/kr/pretty"
)
func validate(value string) error {
return nil
}
var PLID = graphql.NewScalar(graphql.ScalarConfig{
Name: "PLID",
Serialize: func(value interface{}) interface{} {
return value
},
ParseValue: func(value interface{}) interface{} {
var err error
switch value.(type) {
case string:
err = validate(value.(string))
default:
err = errors.New("Must be of type string")
}
if err != nil {
// panic(err) // TODO: This panic kills the server
}
return value
},
ParseLiteral: func(valueAst ast.Value) interface{} {
if valueAst.GetKind() == kinds.StringValue {
err := validate(valueAst.GetValue().(string))
if err != nil {
panic(err)
}
return valueAst
} else {
panic("Must be of type string")
}
},
})
type User struct {
ID string `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
}
var RootMutation = graphql.NewObject(graphql.ObjectConfig{
Name: "Mutation",
Fields: graphql.FieldConfigMap{
"UserLogin": &graphql.FieldConfig{
Name: "UserLogin",
Type: PLID, // output is defined as our custom PLID scalar type.
Args: graphql.FieldConfigArgument{
"email": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
},
"password": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
},
},
Resolve: func(p graphql.GQLFRParams) interface{} {
// let's just print to verify that we have passed the variables correctly
// expected output:
// Arguments map[string]interface {}{
// "email": "[email protected]",
// "password": "donkeykong",
// }
pretty.Println("Arguments", p.Args)
// marshall and cast the arguments
email, _ := p.Args["email"].(string)
password, _ := p.Args["password"].(string)
// perform mutation operation here
// ...
user := &User{
ID: "id007" + email + password,
Email: email,
Password: password,
}
// I'm assuming this is the desired output (i.e. user.ID: PLID)
return user.ID
},
},
},
})
var RootQuery = graphql.NewObject(graphql.ObjectConfig{
Name: "Query",
Fields: graphql.FieldConfigMap{
"currentID": &graphql.FieldConfig{
Type: graphql.String,
},
},
})
func main() {
// define our schema.
// note that while mutation is optional, root query is not. So we defined a trivial root query here.
mutationsTestSchema, err := graphql.NewSchema(graphql.SchemaConfig{
Query: RootQuery,
Mutation: RootMutation,
})
if err != nil {
panic(err)
}
// the variables that would be passed into `graphql`
// I've intentionally used `emailVar` and `passwordVar`
// to make the mutation query easier to understand
variables := map[string]interface{}{
"emailVar": "[email protected]",
"passwordVar": "donkeykong",
}
// our mutation query
request := `
mutation Crud($emailVar: String!, $passwordVar: String!) {
UserLogin(email: $emailVar, password: $passwordVar) {
user {
id
name
email
}
}
}
`
p := graphql.Params{
Schema: mutationsTestSchema,
VariableValues: variables,
RequestString: request,
}
result := graphql.Graphql(p)
pretty.Println(result)
// Expected output:
// &graphql.Result{
// Data: map[string]interface {}{
// "UserLogin": "[email protected]",
// },
// Errors: nil,
// }
}
Output
Arguments map[string]interface {}{
"email": "[email protected]",
"password": "donkeykong",
}
&graphql.Result{
Data: map[string]interface {}{
"UserLogin": "[email protected]",
},
Errors: nil,
}
Notes:
- No changes to your original
PLID
Scalar definition, besides updating the API. - Notice that the schema definition for mutation using pure GraphQL is much simpler than Relay.
- Define your inputs using
Args
. - Define your output type using
Type
- Define your mutation operation in the
Resolve
function, and return the value that matches the output type defined previously inType
- Define your inputs using
- I've intentionally used
emailVar
andpasswordVar
for the keys in the input variables to highlight the differences in the mutation query. - Note the PLID has to be a scalar value (i,e string, boolean, int, etc). Your original example returned a struct instead, probably thats why the output got stringified.
Hope this help a little! Cheers!
from graphql.
Hi @sogko,
Thanks for looking into this and the pure graphql example. My thoughts here was when I return the user struct for a scalar type like graphql.String Type,
user := &User{
ID: "id007",
Email: email,
Password: password,
}
Arguments map[string]interface {}{
"email": "[email protected]",
"password": "donkeykong",
}
&graphql.Result{
Data: map[string]interface {}{
"UserLogin": "&{id007 [email protected] donkeykong}",
},
Errors: nil,
}
it serializes it as a string so my web response will be like this
{
"data": {
"UserLogin": "&{id007 [email protected] donkeykong}",
}
}
but If I use a scalar type PLID then my response Is like this,
{
"data": {
"UserLogin": {
"id": "007",
"password": "bash"
}
}
}
(I haven't tried this yet in the new version and using graphiql will do it soon)
I thought Scalar's can only return one value and not objects, Based on the response it looks like my UserLogin Ouput is an ObjectType with fields id and password which is not true. This became an issue when I noticed the password also present as I forgot to remove it from the struct which could become dangerous, as we could expose other important data accidentally using scalars.
But Now I notice the serialize part of the PLID scalar and I think I should be doing the type conversion there and returning only the ID.
So I was wondering should'nt graphql throw an error if we return an object for a Scalar Type, I still have to re-implement this in graphql-js and see if it happens there also.
from graphql.
Related Issues (20)
- The code generator does not take into account naming conflicts HOT 1
- How to take metro in graphql out of the solve?
- Is this project still mantained? HOT 2
- 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
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.