Greetings, Apollo team!
Consider the following type definitions that will be used to build an Apollo Federation schema:
directive @something(rules: [Rule!]!) on OBJECT | FIELD_DEFINITION
enum Number {
one
two
}
input Rule {
numbers: [Number!]!
}
type Something {
id: ID!
}
extend type Query {
getSomething(id: ID!): Something!
@something(rules: [{ numbers: [one, two] }])
}
A single directive called @something is declared, that takes in a non-nullable list of GraphQL input object types. This directive can then be used on objects and field definitions to perform some task. An example of a similar directive can be found here: https://docs.amplify.aws/cli/graphql-transformer/auth#auth.
The problem arises during composition of the schema, namely that input type Rule is being registered twice, leading to this error: https://github.com/graphql/graphql-js/blob/00eab30fb269b6e2a4e8e61d097d3e249319420e/src/type/schema.js#L223.
I originally posted the issue in graphql-js repository: graphql/graphql-js#2845
Upon further investigation, it appears that the actual problem occurs during schema transformation:
|
typeMap[newType.name] = recreateNamedType(newType); |
The problem is that recreateNamedType creates a new instance of a named type and changes its internal JS object reference. However, graphql package insists on that JS references are kept intact during schema composition, since it uses a Set.has check to ensure types are not registered twice.
As far as I can see, there is no need to use recreateNamedType if type remains the same in
|
typeMap[newType.name] = recreateNamedType(newType); |
Perhaps replacing the following code:
// Returning `undefined` keeps the old type.
const newType = result || oldType;
typeMap[newType.name] = recreateNamedType(newType);
with the following can fix the problem?
// Returning `undefined` keeps the old type.
typeMap[oldType.name] = oldType || recreateNamedType(result);
At least it seems to work when I change it in my local node_modules.
I published an example repository to illustrate the problem: https://github.com/azaxarov/graphql-service-with-complex-directive-parameter
Hope to hear from you guys!
Greetings, Apollo team!
Consider the following type definitions that will be used to build an Apollo Federation schema:
A single directive called
@somethingis declared, that takes in a non-nullable list of GraphQL input object types. This directive can then be used on objects and field definitions to perform some task. An example of a similar directive can be found here: https://docs.amplify.aws/cli/graphql-transformer/auth#auth.The problem arises during composition of the schema, namely that input type
Ruleis being registered twice, leading to this error: https://github.com/graphql/graphql-js/blob/00eab30fb269b6e2a4e8e61d097d3e249319420e/src/type/schema.js#L223.I originally posted the issue in
graphql-jsrepository: graphql/graphql-js#2845Upon further investigation, it appears that the actual problem occurs during schema transformation:
apollo-tooling/packages/apollo-graphql/src/schema/transformSchema.ts
Line 46 in dc4fe35
The problem is that
recreateNamedTypecreates a new instance of a named type and changes its internal JS object reference. However,graphqlpackage insists on that JS references are kept intact during schema composition, since it uses aSet.hascheck to ensure types are not registered twice.As far as I can see, there is no need to use
recreateNamedTypeif type remains the same inapollo-tooling/packages/apollo-graphql/src/schema/transformSchema.ts
Line 46 in dc4fe35
Perhaps replacing the following code:
with the following can fix the problem?
At least it seems to work when I change it in my local
node_modules.I published an example repository to illustrate the problem: https://github.com/azaxarov/graphql-service-with-complex-directive-parameter
Hope to hear from you guys!