Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fields on _operators are lost on child resolvers when using discriminators #390

Open
tatejones opened this issue Nov 3, 2021 · 0 comments

Comments

@tatejones
Copy link

When using discriminators the prepareChildResolver process (copyResolverArgTypes) will treat _operators, AND and OR as fields and call extendField from the baseResolver args to the childResolver args. This will overwrite the contents of these fields removing any specialisation found in the child resolver.

A child based query will result in a GraphQLError

        clickedLinkEventFindMany( filter: { AND: [ { _operators: { url: { in: [ "url1", "url2" ] } } } ] }) {
          __typename
          refId
          url
        }
"errors": Array [
     [GraphQLError: Field "url" is not defined by type "FilterFindManyEventOperatorsInput".],
 ],

Note: it has no knowledge of the "FilterFindManyClickedLinkEventOperatorsInput" as it has been overwritten by "FilterFindManyEventOperatorsInput"

The issue is with copyResolverArgTypes on ./src/discriminators/prepareChildResolvers.ts

 for (const baseArgField of baseResolverArgTCFields) {
          if (childResolverArgTC.hasField(baseArgField) && baseArgField !== '_id') {
            childResolverArgTC.extendField(baseArgField, {
              type: baseResolverArgTC.getField(baseArgField).type,
            });
          }
        }

It checks for '_id', but '_operators', 'AND' and 'OR' are extended overwriting the childResolver details.

I believe the fix is

@@ -85,7 +86,10 @@ function copyResolverArgTypes(
         const baseResolverArgTCFields = baseResolverArgTC.getFieldNames();
 
         for (const baseArgField of baseResolverArgTCFields) {
-          if (childResolverArgTC.hasField(baseArgField) && baseArgField !== '_id') {
+          if (
+            childResolverArgTC.hasField(baseArgField) &&
+            ['_id', OPERATORS_FIELDNAME, 'OR', 'AND'].indexOf(baseArgField) === -1
+          ) {
             childResolverArgTC.extendField(baseArgField, {
               type: baseResolverArgTC.getField(baseArgField).type,
             });

Integration test that produces the problem

Must have an index field to be included in _operators

 const eventSchema = new mongoose.Schema(
    { refId: String, name: { type: String, index: true } },
    options
  );
  it('perform filter operation on a child model', async () => {
    // let's check graphql response
    await Event.deleteMany({});
    await Event.create({ refId: 'aaa', name: 'aName' });
    await Event.create({ refId: 'bbb', name: 'bName' });
    await ClickedLinkEvent.create({ refId: 'ccc', name: 'cName', url: 'url1' });
    await ClickedLinkEvent.create({ refId: 'ddd', name: 'dName', url: 'url2' });

    schemaComposer.Query.addFields({
      clickedLinkEventFindMany: ClickedLinkEventTC.getResolver('findMany'),
    });

    const schema = schemaComposer.buildSchema();

    const res = await graphql.graphql(
      schema,
      `{
        clickedLinkEventFindMany( filter: { AND: [ { _operators: { url: { in: [ "url1", "url2" ] } } }, { name: "dName" } ] }) {
          __typename
          refId
          name
          url
        }
      }`
    );

    expect(res).toEqual({
      data: {
        clickedLinkEventFindMany: [
          { __typename: 'ClickedLinkEvent', refId: 'ddd', name: 'dName', url: 'url2' },
        ],
      },
    });
  });

A pull request will be made and the appropriate fix plus tests will be submitted for review.

tatejones added a commit to tatejones/graphql-compose-mongoose that referenced this issue Nov 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant