aPureBase / KGraphQL

Pure Kotlin GraphQL implementation
https://kgraphql.io
MIT License
298 stars 58 forks source link

Detect absence of optional input fields #192

Closed IceBlizz6 closed 2 years ago

IceBlizz6 commented 2 years ago

Example with use case

In my application i have a mutation that lets someone edit objects on the server. In this example i am creating a new user.

mutation {
    createUser(
        input: { name: "IceBlizz6", email: "em1@nowhere.com" }
    ) 
}

Then i edit the name on the user, notice absence of email field in editUser.

mutation {
    editUser(
        id: 1,
        input: { name: "IceBlizz7" }
    )
}

How it works in java.graphql

Using graphql-java's DataFetchingEnvironment i am able to get list of inputs that is sent in the request. I can then see that email field is absent and only name is present. So the server will then only update the name field. This is important because after deserialization the email field in Kotlin will be null (as it is optional for editUser input). So i need to differentiate between "field was sent as null" and "field was not present in the request".

What i want

Would it be possible to get something similar in KGraphQL?

This can currently not be solved with Context as several mutations can be called in the same request, and same Context has to be shared between all of them.

Let me know if this needs further clarification. Thank you.

jeggy commented 2 years ago

This is possible via a special argument, just like how the Context is a special argument. You can in your resolver request the argument called Execution.Node and this will be provided just like how the Context is provided and it will not be exposed to your graphql schema.

You can see a simple sample here: https://github.com/aPureBase/KGraphQL/blob/main/kgraphql/src/test/kotlin/com/apurebase/kgraphql/integration/QueryTest.kt#L314

On the Execution.Node you have access to .getFields() and arguments and here you can find all information you need.

IceBlizz6 commented 2 years ago

@jeggy Thank you very much. That is exactly what i was looking for.

I was unable to find something like this in the documentation, so i assumed that it didn't exist. It only lists Context as a possible option. One suggestion could be to include a full list of all types that can be injected as parameters like this in the documentation.

PssbleTrngle commented 1 year ago

This works for detecting which input fields a request has sent, but not if the request is using variables. In that case, the input node is of type ValueNode.VariableNode and not ValueNode.ObjectValueNode. Is there a way to gather the same information by resolving the VariableNode using the Execution.Node?