I just came across some aspects of this in trying to use addMocksToSchema
and hitting the underlying issue. I thought I would share my findings here and the workaround I’ve found.
When using the high level functions like addResolversToSchema
, you want to make sure you are updating the resolvers in place which will use the existing schema: addResolversToSchema({ schema, resolvers, updateResolversInPlace:true })
With the lower-level functions like mapSchema
, the associated __resolveReference
resolvers for any defined Entities are lost in normalization. The workaround by @vad3x can be used to fix this, but you don’t need to worry about the prefix which could be simplified to the following:
function fixResolveReferenceNormalization(originalSchema, normalizedSchema) {
const typeMap = originalSchema.getTypeMap();
const mockedTypeMap = normalizedSchema.getTypeMap();
for (const [name, type] of Object.entries(typeMap)) {
if (isObjectType(type) && typeMap[name].resolveReference) {
mockedTypeMap[name].resolveReference = typeMap[name].resolveReference;
}
}
}
Basically copying the entity.__resolveReference implementation from the original schema to the normalized schema.
If you are using addMocksToSchema
, it uses all of this under the hood, but you have to call this after buildSubgraphSchema
is called. This ends up wiping out the _Entity
union definition that is added for you by buildSubgraphSchema
in the normalization process. This is an easier workaround where you can just define that in addMocksToSchema
:
const mockedSchema = addMocksToSchema({
schema,
resolvers: {
_Entity: {
__resolveType(parent) {
return parent.__typename;
},
},
},
preserveResolvers: true,
mocks,
});
Now you have a mocked schema, but it will be missing the entity.__resolveReference
which you can add back with the function referenced as the workaround for mapSchema
:
const mockedSchema = addMocksToSchema({
schema,
resolvers: {
_Entity: {
__resolveType(parent) {
return parent.__typename;
},
},
},
preserveResolvers: true,
mocks,
});
fixResolveReferenceNormalization(schema, mockedSchema);
schema = mockedSchema;
Whew, all the normalization basically removes the _Entity
union definition aspects and Entity __resolverReference definitions. From what I can see, this normalization is happening with copying schema artifacts into a new schema object that uses the standard graphql objects (like GraphQLObjectType
) and there is also a toConfig
helper method that is used in copying the old config to the new object.