Are fields with list types forbidden in GraphQL schema stitching selection sets?

Viewed 176

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 } }'
}
1 Answers

You have likely found a bug! Please open an issue on the GitHub repo so we can track it. :)

Related