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

On mutation of stitched schema, executed query on merged type #4508

Open
4 tasks
Tracked by #5201 ...
kftsehk opened this issue Jun 5, 2022 · 1 comment
Open
4 tasks
Tracked by #5201 ...

On mutation of stitched schema, executed query on merged type #4508

kftsehk opened this issue Jun 5, 2022 · 1 comment

Comments

@kftsehk
Copy link

kftsehk commented Jun 5, 2022

Issue workflow progress

Progress of the issue based on the Contributor Workflow

  • 1. The issue provides a reproduction available on Github, Stackblitz or CodeSandbox

    Make sure to fork this template and run yarn generate in the terminal.

    Please make sure the GraphQL Tools package versions under package.json matches yours.

  • 2. A failing test has been provided
  • 3. A local solution has been provided
  • 4. A pull request is pending review

Describe the bug

If a graphql query is mutation, at step 4 onward, query is being executed instead of mutation

image
https://www.graphql-tools.com/docs/schema-stitching/stitch-type-merging#merging-flow

If such field name is not defined in Query of stitched schema, the merged resolver fails silently returning null result.

To Reproduce

cd gateway
npm i
pip install awscli aws-sam-cli
sam local start-api -t ./local.yml -l message.log --host 0.0.0.0 -p 3000

Example 1: Has Mutation.*User, not Query.*User

https://github.com/flyingmilktea/graphql-bug-reproduce/tree/mutation-fwd-query-v1

mutation {
  # or oneUser, which zeroValue becomes null
  zeroUser(id: 1) {
    __typename
    id
    zeroValue
    oneValue
    user {
      __typename
      id
      zeroValue
      oneValue
    }
  }
}

Result:

{
  "data": {
    "zeroUser": {
      "__typename": "User",
      "id": "1",
      "zeroValue": "0: User: mutation",
      "oneValue": null,
      "user": {
        "__typename": "User",
        "id": "1",
        "zeroValue": "0: User: mutation",
        "oneValue": null
      }
    }
  }
}

Example 2: Added Query.*User to both server

https://github.com/flyingmilktea/graphql-bug-reproduce/tree/mutation-fwd-query-v2

mutation {
  # or oneUser, which zeroValue becomes query
  zeroUser(id: 1) {
    __typename
    id
    zeroValue
    oneValue
    user {
      __typename
      id
      zeroValue
      oneValue
    }
  }
}
{
  "data": {
    "zeroUser": {
      "__typename": "User",
      "id": "1",
      "zeroValue": "0: User: mutation",
      "oneValue": "1: User: query",
      "user": {
        "__typename": "User",
        "id": "1",
        "zeroValue": "0: User: mutation",
        "oneValue": "1: User: query"
      }
    }
  }
}

Expected behavior

{
  "data": {
    "zeroUser": {
      "__typename": "User",
      "id": "1",
      "zeroValue": "0: User: mutation",
      "oneValue": "1: User: mutation",
      "user": {
        "__typename": "User",
        "id": "1",
        "zeroValue": "0: User: mutation",
        "oneValue": "1: User: mutation"
      }
    }
  }
}

Environment:

  • OS: Linux 4.18.0-372.9.1.el8.x86_64
  • "@graphql-tools/graphql-file-loader": "^7.3.14",
  • "@graphql-tools/load": "^7.5.13",
  • "@graphql-tools/schema": "^8.3.13",
  • "@graphql-tools/stitch": "^8.6.12",
  • "@graphql-yoga/node": "^2.8.0",
  • "@vendia/serverless-express": "^4.8.0",
  • NodeJS: v14.19.3

Additional context

export function createMergedTypeResolver<TContext extends Record<string, any> = any>(
mergedTypeResolverOptions: MergedTypeResolverOptions
): MergedTypeResolver<TContext> | undefined {
const { fieldName, argsFromKeys, valuesFromResults, args } = mergedTypeResolverOptions;
if (argsFromKeys != null) {
return function mergedBatchedTypeResolver(
_originalResult,
context,
info,
subschema,
selectionSet,
key,
type = getNamedType(info.returnType) as GraphQLOutputType
) {
return batchDelegateToSchema({
schema: subschema,
operation: 'query' as OperationTypeNode,
fieldName,
returnType: new GraphQLList(type),
key,
argsFromKeys,
valuesFromResults,
selectionSet,
context,
info,
skipTypeMerging: true,
});
};
}
if (args != null) {
return function mergedTypeResolver(
originalResult,
context,
info,
subschema,
selectionSet,
_key,
type = getNamedType(info.returnType) as GraphQLOutputType
) {
return delegateToSchema({
schema: subschema,
operation: 'query' as OperationTypeNode,
fieldName,
returnType: type,
args: args(originalResult),
selectionSet,
context,
info,
skipTypeMerging: true,
});
};
}
return undefined;
}

The problem likely caused by operation: "query" being hardcoded into default createMergedTypeResolver, actually changing to operation: info.operation.operation on both occurrence will fix it.

Still I do not understand the origin that, no error is thrown for the example of v1 even it is a validation error at stitched schema (Attempt to run Query.fieldName while only Mutation.fieldName exists).

  • For v1, In the case of using a remote executor at step 4, no query is received on the remote server.

Thanks @Abbywpy for help on testing the problem

@ardatan
Copy link
Owner

ardatan commented Jun 5, 2022

Thank you for explanation!
Would you create a PR with a failing test?

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

2 participants