Different enum treatment in Federation Module
I'm submitting a...
[ ] Regression
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
repro: https://github.com/Boshen/nestjs-playground
This is going to be hard one ... but here we go,
Current behavior
With GraphQLFederationModule, https://github.com/Boshen/nestjs-playground/blob/master/src/app.module.ts#L18-L20
GraphQLFederationModule.forRoot({
autoSchemaFile: true,
}),
and this reduced introspection query (reduced from when you try to get the schema):
query IntrospectionQuery {
__schema {
types {
name
inputFields {
name
defaultValue # <-- this guy
}
}
}
}
the enum type gets treated differently in the defaultValue field of an input field https://github.com/Boshen/nestjs-playground/blob/master/src/author.resolver.ts
enum AuthorType {
XXX,
YYY,
}
registerEnumType(AuthorType, {
name: 'AuthorType',
})
@InputType()
class AuthorInput {
@Field()
name!: string
@Field(() => AuthorType)
authorType: AuthorType = AuthorType.XXX // <---- this guy here
}
By comparing the output from the following error in graphql source code:
"message": "Enum \"AuthorType\" cannot represent value: \"XXX\"",
"stacktrace": [
"GraphQLError: Enum \"AuthorType\" cannot represent value: \"XXX\"",
" at GraphQLEnumType.serialize (/Users/boshen/github/nestjs-playground/node_modules/graphql/type/definition.js:1006:13)",
node_modules/graphql/type/definition.js:1006 source:
_proto5.serialize = function serialize(outputValue) {
var enumValue = this._valueLookup.get(outputValue);
if (enumValue === undefined) {
throw new _GraphQLError.GraphQLError("Enum \"".concat(this.name, "\" cannot represent value: ").concat((0, _inspect.default)(outputValue)));
}
return enumValue.name;
};
GraphQLFederationModule outputs the _valueLookup Map as
Map(2) {
0 => {
name: 'XXX',
description: undefined,
value: 0,
isDeprecated: false,
deprecationReason: undefined,
extensions: undefined,
astNode: undefined
},
1 => {
name: 'YYY',
description: undefined,
value: 1,
isDeprecated: false,
deprecationReason: undefined,
extensions: undefined,
astNode: undefined
}
But in the normal graphql module, it outputs 'XXX', 'YYY' as the Map keys.
I think this has something to do with GraphQLFederationModule parsing the values during request, but normal GraphQLModule parses during application start time?
The easy fix is obviously:
enum AuthorType {
XXX = 'XXX',
YYY = 'YYY'
}
But two hours wasted cracking this ;-)
Would you like to create a PR for this issue?
Would you like to create a PR for this issue?
This is way too complicated for me, I couldn't find the root cause ...
i just encountered this with federation as well. this error does not present itself if you are not using federation
Hi there,
I noticed this discussion about the error handling issues with GraphQL in NestJS, and I'm facing the same problem. I've tried some of the suggestions mentioned here, such as using a middleware or the "debug" option, but I still can't seem to get meaningful error messages when a GraphQL query fails.
I'm wondering if anyone has found a solution or workaround for this issue since this discussion was last updated. Any insights or suggestions would be greatly appreciated.
Thanks in advance!
I dug into this issue and found that it's due to the federated schema factory using printSubgraphSchema from
@apollo/subraph, while the default schema factory uses makeExecutableSchema from graphql-tools. makeExecutableSchema takes a resolvers parameter which means it can make the correct graphql enum default value, while printSubgraphSchema does not take a resolvers param so it doesn't behave correctly here. To fix the problem, Apollo will need to add a resolvers parameter to their printSubgraphSchema command, or nestjs will have to do a band-aid on the output of that function to correct the enum values.
Hey @kbrooks - it sounds like you might have a better grasp on the issue than I do. I'm trying to find the discrepancy but not sure I'm looking in the right place. My attempt to reproduce shows the same result (for the original introspection query) w.r.t. the field on the input type and its defaultValue (vs. a schema build using buildSchema from graphql-js).
https://github.com/apollographql/federation/compare/trevor/print-input-field-default-issue?expand=1
What can I add to this test case to demonstrate the issue? Do I need resolvers in order to resolve the MyEnum.A value to something that isn't "A" perhaps?
Here is a patch you can apply which creates two test cases you can use to debug the issue repro.patch
The reason I believe it is related to resolvers is that the resolvers contain the type information to map the graphql enum value to the TypeScript one. So if your nest.js ts enum looks like this
enum SpiceLevel {
ZERO
ONE
TWO
THREE
}
Then the underlying values are going to be 0,1,2,3 and not "ZERO", "ONE" etc.
@kbrooks got it. Opened an issue on our repo for it. I'm not sure when we we'll be able to address this, but happy to review a PR if you're feeling motivated or in a hurry to get this resolved.