-
-
Notifications
You must be signed in to change notification settings - Fork 816
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
Update to graphql-js
14.x
#953
Conversation
Hopefully everyone is okay with this; that 110 char ruler was really throwing me off! :-)
All tests are using `graphql` 14.x now.
Linking in the PR's that need to be addressed with this one: apollographql/apollo-link#789 |
Waiting on apollographql/graphql-subscriptions#172 before we can finalize this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only one item which I think warrants tweaking, but otherwise, LGTM!
Nice work here!
@@ -51,6 +52,10 @@ function addResolveFunctionsToSchema( | |||
? extendResolversFromInterfaces(schema, inputResolvers) | |||
: inputResolvers; | |||
|
|||
// Used to map the external value of an enum to its internal value, when | |||
// that internal value is provided by a resolver. | |||
const enumValueMap = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than using the object literal notation, which inherits from Object.prototype
, I believe we should be careful to use Object.create(null)
here since the result of getType(...).name
(a user-controlled string) could get set into it — potentially a problem with JavaScript internal properties like length
, prototype
, etc.
For example, without this (unless this is caught somewhere else that I'm missing?) weird behavior could ensue when the return value of getType(...).name
is set into enumValueMap
via enumValueMap[valueReturnedFromGetTypeName] =
:
const sdl = `
enum length { LONG SHORT }
type Query { long: length }
`;
require("graphql")
.buildSchema(sdl)
.getType("length").name; // "length"
(And similarly with say, constructor
or prototype
in place of length
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes, great point @abernix - I'll adjust, thanks!
@@ -88,9 +88,10 @@ export function recreateType( | |||
const newValues = {}; | |||
values.forEach(value => { | |||
newValues[value.name] = { | |||
value: value.name, | |||
value: value.value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I inquire more details about this particular change (name
to value
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing! Normally when using a GraphQLEnumType
object, the name
and value
properties of an enum value are the same. E.g. Color.RED
would have RED
stored as both it's name
and value
. graphql-tools
internal enum value support however needs to store the new internal value we want to use into the new GraphQLEnumType
value that's created. We have to keep the name
of the value the same as it was before (e.g. name stays as RED
), but here we're adjusting the value
to be the new internal value that's coming from the enum resolver (that we setup in src/generate/addResolveFunctionsToSchema.ts
).
We could have added some logic in here to only change the value
to value.value
when we have enum resolvers setup (in other words only when we want to use new internal enum values), but since value
is always the same as name when using a normal enum without any internal values, this code change should work in both cases.
Enum with an external value only:
Color.RED
--> name
= RED
, value
= 'RED'
Enum with an external and internal value:
Color.RED
--> name
= RED
, value
= '#ff0000'
So using value.value
in value
in both cases above gives us what we need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent explanation. Thank you!
This PR updates the
graphql-tools
peerDependencies
to allowgraphql
14.x, and enforcesgraphql
14.x in itsdevDependencies
. All changes have been made in a way that is backwards compatible withgraphql
0.13.x, but anyone looking to upgrade tographql
14.x should keep in mind thatgraphql
14.x introduced several breaking changes. Because of this we're likely going to major version bumpgraphql-tools
for the next release.Most of the changes in this PR are pretty straightforward, with one main exception. The current version of
graphql-tools
is relying ongraphql
0.13 functionality to achieve internal enum value support.graphql
14.x has tightened up public facing API access, which means the current method of handling internal enum values no longer works withgraphql
14.x. Because of this, we now have to transform existing enums into new enums that include an internal value. This means we're adding a new schema transformation step to schema's that include enums with enum resolvers.Fixes #945.
Work remaining:
@types/graphql
graphql
14.x in all peer projects and get new versions published (apollo-link
,graphql-subscriptions
)