GraphQL error: Variable 'id' has coerced Null value for NonNull type 'ID!' - graphql

I am using the AWS AppSync service as my GraphQL server. I am passing a mutation GraphQL tag to create a user but somehow I am getting this error in the console:
GraphQL error: Variable 'id' has coerced Null value for NonNull type 'ID!'
The mutation GraphQL tag is like this:
import gql from 'graphql-tag';
export default gql`
mutation addUser ($id:ID!,$name:String!,$email:String!,$number:String!,$gender:String!,$password:String!,$createdAt:String!,$type:String!){
addUser(
id:$id,
name:$name,
email:$email,
number:$number,
gender:$gender,
password:$password,
createdAt:$createdAt,
type:$type
){
id
name
email
}
}`;
and I am passing this GraphQL tag inside my SignupForm.js to create a user like this:
export default graphql(AddUser,{
props:props=>({
AddUser:user=>props.mutate({
variable:user,
})
})
})(SignUpForm);
When I call this.props.AddUser(user)
where user is signup user details object
I got error mentioned above.

It seems the problem is a typo in the mutation options:
{ variable: user } should be { variables: user } (with an 's')

Related

GraphQL Relay introspection query fails: Unknown field '__type' on type 'Query'

I have a React application with a GraphQL client (Relay).
I need to make an introspection query to get all the types of a certain enum.
This is my query:
import { graphql } from 'react-relay'
export const corporationTypeEnumQuery = graphql`
query corporationTypeEnumQuery {
__type(name: "CorporationTypeEnum") {
enumValues {
name
}
}
}
`
When I try to compile the app, Relay throws the following error:
Unknown field '__type' on type 'Query'
When I try the exact same query on GraphIQL (the playground that the server offers me), there is no error, and the query is successful.
Please tell me what could be wrong with my GraphQL query. Any suggestions are well received.
The __type must be part of your schema. Graphql spec by default said this should be hidden and not part of schema.. You need to extend your server to expose it or manually put them to schema..
Server can handle that but compiler not since it require explicit definition in .graphql

Error when trying to delete in AWS AppSync

I am using Graphql within AWS AppSync. I can create items with no issues but when i try to delete one i get this error.
ConflictUnhandled - Conflict resolver rejects mutation.
i am using
deleteFavorite(input: {id: "ce8dfa4c-ef87-492e-9a87-f17d2f0b06c8", _version: 1})
from this auto created mutation
export const deleteFavorite = /* GraphQL */ `
mutation DeleteFavorite(
$input: DeleteFavoriteInput!
$condition: ModelFavoriteConditionInput
) {
deleteFavorite(input: $input, condition: $condition) {
id
productID
useremail
userID
_version
_deleted
_lastChangedAt
createdAt
updatedAt
}
}
`;
The answer was to make sure i was passing the same _version back to the delete rewuest

Omitting the field in response with GraphQL Apollo

I am using Apollo GraphQL server and directives.
Here is my simple schema. Notice the directive on the token field, User type.
const typeDefs = `
directive #allow(service: String) on FIELD_DEFINITION
type User {
email: String!
pass: String!
... other fields here
token: String #allow(service: "login")
}
type Mutation {
login(email: String!, pass: String!): User
}`;
I would like to return the token field only if the login has been called. Otherwise, I would like to return the User object without the token field, all I could find is throwing an Exception or returning the null in the "token" field.
class SkipDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field, details) {
const { resolve = defaultFieldResolver } = field;
field.resolve = async function (...args) {
// If called in context different from "login"
// Here I would like to just "delete" the "token" field
else {
const result = await resolve.apply(this, args);
return result;
}
};
}
}
Ideas?
If a field is requested, it should be returned with either a value matching the field's type or else null. To do otherwise would break the spec.
There is no way you can modify this behavior through a schema directive. A field definition directive can only change runtime behavior by modifying the field's resolver. However, by the time the resolver is called, the selection set has already been determined so it's too late to modify it. Returning null or throwing an error are pretty much the only two options.
You might be able to implement some kind of workaround through either the formatResponse option or a custom plugin. However, because this behavior would break the spec, there's no telling if it wouldn't cause issues with client libraries or other tools.

Overload GraphQL Schema to Support getting a user by username or password

I am trying to create a GraphQL Schema such that a user will be able to find a user by their email or username. Imagine for these purposes one user could have an email that is the username of another user.
My typeDefs look as follows:
const typeDefs = gql`
type Query {
user: User(username: String!)
user: User(email: String!)
}
`;
Is this a valid Schema? If not how would I change my solution to be valid and solve my problem?
Edit: So I tried to execute the above and I get an error: 'Error: Field "Query.user" can only be defined once.' As I thought I might.
Is there any way to ensure that exactly one of username and email is null in the following: user: User(username: String, email: String)?
There is no "overloading" of fields in GraphQL, and no syntax that would support one of two fields being required. An argument is either nullable or non-null, that's it. You can do this:
type Query {
user(username: String, email: String): User
}
or this
type Query {
user(filter: UserFilter!): User
}
input UserFilter {
username: String
email: String
}
and then handle validation (at least one argument is defined but not both) inside your resolver. The only other way to do it would be something like:
type Query {
user(key: UserFilterKey!, value: String!): User
}
enum UserFilterKey {
username
email
}
But this kind of approach is not very intuitive for anyone consuming the schema. It also only works if the arguments in question have the same type.

Apollo GraphQL: Resolver not called on mutation subfield

I am trying to return a Query type from a mutation, which I could make work in some cases but not the way I want it. The problem is not particularly related to the Query type being used, as I found the same behaviour using other types than Query.
You can run and modify this code on https://codesandbox.io/s/1z8kjy8m93
Server
const { ApolloServer, gql } = require("apollo-server");
const typeDefs = gql`
type Query {
hello(msg: String): String
}
type Mutation {
someMutation(someArg: String): MutationResponse
}
type MutationResponse {
query: Query
status: String
}
`;
const resolvers = {
Query: {
hello: (root, args, context) => {
console.log("hello: args = ", args);
return `${args.msg}, world !`;
}
},
Mutation: {
someMutation: (root, args, context) => {
console.log("someMutation: args = ", args);
return { status: `Mute Mute: ${args.someArg}` };
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
Mutation
mutation mutateMe($mutationArg: String = "YoloMute !", $helloMsg: String = "Yolhello") {
someMutation(someArg: $mutationArg) {
status
query {
hello(msg: $helloMsg)
}
}
}
Response
{
"data": {
"someMutation": {
"status": "Mute Mute: YoloMute !",
"query": null
}
}
}
I don't understand why the hello resolver is not called and the query field is null.
The status field is duly filled by the someMutation resolver, but as the query field is not resolved there I would expect GraphQL to call an existing resolver for this field, which exists and should be called for the Query type.
I found other ways that technically work but are not satisfying:
Directly returning the Query type works:
https://codesandbox.io/s/ovr9zpwr7q
Duplicating lines in the schema
works: https://codesandbox.io/s/l4yrqzmq6l
This issue isn't really specific to the Query type, but rather deals with how you've set up your resolvers.
The status field is duly filled by the someMutation resolver, but as the query field is not resolved there I would expect GraphQL to call an existing resolver for this field, which exists and should be called for the Query type.
There is no resolver for the entire Query type, or any other type. Resolvers exist only for individual fields of a particular type. When a resolver isn't defined for a field, GraphQL will default to looking for a property on the parent object with the same name as the field, and will return the value of that property.
Let's walk through your document. The root-level field is:
someMutation(someArg: $mutationArg)
The parent value is the root value for all root-level mutations. Unless you're using a custom root value, this will typically be an empty object. If you didn't define a resolver for the someMutation field of the Mutation type, GraphQL would look for a property called someMutation in your root value and return that (i.e. undefined, which would be coerced to null in the response). We do have a resolver, though, and it returns:
{
status: `Mute Mute: ${args.someArg}`,
}
Now, let's resolve the status field. Our parent object is the result returned by the parent field's resolver. In this case, the object above. We have no resolver for status on MutationResponse, so GraphQL looks for a status property on the parent -- it finds one and uses that. status has a Scalar type, so whatever value is returned by the resolver will be coerced into the appropriate scalar value.
What about the query field? Again, we have no resolver for a query field on the MutationResponse. However, we also don't have a property called query on the parent object. So, all GraphQL can do is return null for that field.
Even though the return type for query is an ObjectType, because it resolves to null, any resolvers for fields on that ObjectType will not be fired. Returning null means the object doesn't exist, so we don't need to bother resolving any fields on it. Imagine if a field returned a User object. If it returned null, there would be no need to resolve the user's name, for example.
So... how do we get around this? There's two ways:
Either add a property for query to the object returned by someMutation's resolver, like this:
{
status: `Mute Mute: ${args.someArg}`,
query: {},
}
Or, add a resolver for the field:
MutationResponse: {
query: () => {},
},
Either way will ensure that the query field will resolve to a non-null value (in this case, just an empty object). Because the value resolved is not null and the return type is an ObjectType (in this case Query), now the resolvers for that type's fields will be triggered and hello will resolve as expected.

Resources