I have an array of entities that look like this:
const aEntities = [
{
id: 1,
name: 'Test',
oneToManyRelation: [
{
id: 2
},
{
id: 3
}
],
oneToOneRelation: {
id: 1
}
}
];
The entities are represented by the type AType. I want to make an extension of this type in a separate subschema and prove that it is possible to add fields that derive their values from the contents of oneToOneRelation and oneToManyRelation respectively.
The following schema, implementing a derived field based on oneToOneRelation, works fine:
const aSchema = makeExecutableSchema({
resolvers: {
Query: {
aEntities: () => aEntities
}
},
schemaTransforms: [stitchingDirectivesValidator],
typeDefs: gql`
${allStitchingDirectivesTypeDefs}
type AType {
id: ID!
name: String!
oneToOneRelation: AEmbeddedType!
}
type AEmbeddedType {
id: ID!
}
type Query {
aEntities: [AType!]!
}
`
});
const bSchema = makeExecutableSchema({
resolvers: {
AType: {
oneToOneId: ({ oneToOneRelation }) => oneToOneRelation.id
},
Query: {
aEntities_fromBSchema: (_, { keys }) => keys,
}
},
schemaTransforms: [stitchingDirectivesValidator],
typeDefs: gql`
${allStitchingDirectivesTypeDefs}
type AType @key(selectionSet: "{ oneToOneRelation { id } }") {
oneToOneId: String!
}
scalar Key
type Query {
aEntities_fromBSchema(keys: [Key!]!): [AType!]! @merge
}
`
})
const schema = stitchSchemas({
subschemaConfigTransforms: [stitchingDirectivesTransformer],
subschemas: [
{
schema: aSchema
},
{
schema: bSchema,
}
]
})
But once I add oneToManyRelation { id } to the selectionSet i run into problems:
const aSchema = makeExecutableSchema({
resolvers: {
Query: {
aEntities: () => aEntities
}
},
schemaTransforms: [stitchingDirectivesValidator],
typeDefs: gql`
${allStitchingDirectivesTypeDefs}
type AType {
id: ID!
name: String!
oneToManyRelation: [AEmbeddedType!]!
oneToOneRelation: AEmbeddedType!
}
type AEmbeddedType {
id: ID!
}
type Query {
aEntities: [AType!]!
}
`
});
const bSchema = makeExecutableSchema({
resolvers: {
AType: {
oneToManyIds: ({ oneToManyRelation }) => oneToManyRelation.map(({ id }) => id),
oneToOneId: ({ oneToOneRelation }) => oneToOneRelation.id
},
Query: {
aEntities_fromBSchema: (_, { keys }) => keys,
}
},
schemaTransforms: [stitchingDirectivesValidator],
typeDefs: gql`
${allStitchingDirectivesTypeDefs}
type AType @key(selectionSet: "{ oneToOneRelation { id }, oneToManyRelation { id } }") {
oneToOneId: String!
oneToManyIds: [String!]!
}
scalar Key
type Query {
aEntities_fromBSchema(keys: [Key!]!): [AType!]! @merge
}
`
})
I get the following error:
oneToManyRelation.map is not a function
And when I log the keys parameter in the aEntities_fromBSchema resolver it seems that oneToManyRelation haven't been resolved to be an array at all, but rather an (empty) object:
[
{
oneToOneRelation: [Object: null prototype] { id: '1' },
oneToManyRelation: [Object: null prototype] { id: undefined },
__typename: 'AType'
}
]
Is referencing list types in key selection sets simply forbidden as of graphql-tools v 7.0.2? It looks like I actually can circumvent the issue by using a subschema merge config defined outside of the SDL (without batching, instead using the args and selectionSet config parameters), but for validation/gateway reasons I'd prefer to have all my subschemas contain all of their type merging instructions as SDL directives.
Nb. This is a simplified representation of a real world problem.
Nb2. In the real world application one of my subschemas is a remote GraphQL application that I don't control, hence the need for some advanced tailoring in the stitching layer.
Edit: Simply adding the following to the merge options on the subschema config seems to solve the problem. Someone know of a good reason why this doesn't seem to be reproducible with SDL directives? (Or a good way to do so?)
// AType
{
argsFromKeys: (keys) => ({ keys }),
fieldName: 'aEntities_fromBSchema',
key: ({ oneToOneRelation, oneToManyRelation }) => ({ oneToManyRelation, oneToOneRelation }),
selectionSet: '{ oneToOneRelation { id }, oneToManyRelation { id } }'
}