-
Notifications
You must be signed in to change notification settings - Fork 842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add other integer values to the coerceInt function #83
Conversation
@bbuck The graphql-js release today ( https://github.com/graphql/graphql-js/releases/tag/v0.4.14 With that change, I would think that |
Awesome. Then I will rework this tonight for int values and we can all rejoice. |
So now I also added in a really small bug that I found, where |
Oh, I should also note that I replaced |
Why |
Because it is at least 32 bits in size and is the default type assigned to literals. Instead of casting all of your numbers as |
Makes sense. Thanks for the explanation! |
@sogko @chris-ramon Any status on when this will get merged? This is a major feature I need to consume this library. |
Great work on this @bbuck, thanks a lot! 🌟 This def looks to me 👍 I think we can handle the |
Add other integer values to the coerceInt function
The Enum problem isn't really an issue now that it's back to |
Hi @bbuck! - the package main
import (
"encoding/json"
"fmt"
"log"
"github.com/graphql-go/graphql"
)
func main() {
roleEnum := graphql.NewEnum(graphql.EnumConfig{
Name: "roles",
Values: graphql.EnumValueConfigMap{
"ADMIN": &graphql.EnumValueConfig{
Value: 1,
},
"USER": &graphql.EnumValueConfig{
Value: 2,
},
},
})
fields := graphql.Fields{
"roles": &graphql.Field{
Type: graphql.NewList(roleEnum),
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return []int{1, 2}, nil // []int8{1, 2}, nil -> won't work
},
},
}
rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields}
schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)}
schema, err := graphql.NewSchema(schemaConfig)
if err != nil {
log.Fatalf("failed to create new schema, error: %v", err)
}
query := `
{
roles
}
`
params := graphql.Params{Schema: schema, RequestString: query}
r := graphql.Do(params)
if len(r.Errors) > 0 {
log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors)
}
rJSON, _ := json.Marshal(r)
fmt.Printf("%s \n", rJSON) // {"data":{"roles":["ADMIN","USER"]}} - {"data":{"roles":[null,null]}}
} |
That is definitely the issue I had when I originally made this pull request to support only In your example, I see two possible course of action that would (or should be taken) if employed in a live project. The first is, if you're resolving with roleEnum := graphql.NewEnum(graphql.EnumConfig{
Name: "roles",
Values: graphql.EnumValueConfigMap{
"ADMIN": &graphql.EnumValueConfig{
Value: int8(1),
},
"USER": &graphql.EnumValueConfig{
Value: int8(2),
},
},
}) While the other option is more idiomatic I would think. First you would create an enum type internally in the program: type Role int8
const (
RoleAdmin Role = iota + 1
RoleUser
) And then modify the resolution function: // ...
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return []Role{RoleAdmin, RoleUser}, nil
},
// ... And the problem dissipates itself. I don't think there is an ideal method to match arbitrary types to other types in this situation (in the example, matching an tl;dr I don't think it's an issue that would be worth resolving. |
That makes totally sense! - thanks @bbuck. I agree this |
This pull request will fix #22.
As a note, I added several more cases to the
coerceInt
function to support the sizedint
anduint
types and well as unsized uint types. I unified the integer return value from the function toint64
.Reasoning for
int64
returnsPast discussions that have been lost discussed returning the value that was sent but this breaks down quickly when parsing queries the values given are strings and a choice has to be made at that point how to parse them. I attempted to implement my best guess despite that fact and so if a value was passed in, I returned the closest, most appropriate, int sized value but this in itself is error prone. Just because the number fits in an
int8
doesn't mean it was anint8
or anint8
is expected.Given the spec for GraphQL (and the fuzzy number used by this library) for minimum/maximum values it's clear than an
int64
is required. The previous use ofint
could functionally work so long as nobody ever built for a 32-bit architecture at which point theint
value would be too small and errors would appear from every which way. Taking this into consideration and the fact that "guessing" at the appropriate type are both error prone in their own way I chose to forgo that and useint64
as the integer type when interfacing with GraphQL.I'm open to discussion around this decision but I think it's the right way to go. Although several tests had to be adjusted to accommodate it I still feel it's the best direction we go to keep things working smoothly which such a varying type.
NOTE: I just want to mention a funky side effect that I encountered with tests. In order for enums associated to integer values to be fetched they have to be defined with
int64
values, otherwise the lookup will fail. This is non-ideal as it restricts the users choice in types to use but I can't think of an immediate solution that would solve this. Returning the "best guess" type will also fail out here ifint16
is used and anint8
is returned.