Search code examples
typescriptgraphqlapollo

How do I run my GraphQL query for mutation using variable object


Below is my Register Mutation GraphQL Query, when I run it I get an error. "Errormessage": "Variable "$options" of type "UsernamePasswordInput" used in position expecting type "UsernamePasswordInput!".",strong text How do I run my GraphQL query for mutation using variable object UsernamePasswordInput.

Thank you for your help.

mutation($options: UsernamePasswordInput){
  register(options: $options){
    errors {
      field
      message
    }
    user {
      id
      username
    }
  }
}

Below GraphQL works just fine but how do I use Variable object.

mutation{
  register(options: { username: "test6",password:"test6"}){
    errors {
      field
      message
    }
    user {
      id
      username
    }
  }
}

Below is the code for my resolver

@InputType()
class UsernamePasswordInput {
    @Field()
    username: string;
    @Field()
    password: string;
} 

@ObjectType()
class FieldError {
    @Field()
    field: string;    
    @Field()
    message: string;
}

@ObjectType()
class UserResponse {
    @Field(() => [FieldError], { nullable: true } )
    errors?: FieldError[];

    @Field(() => User, { nullable: true } )
    user?: User;
}

@Resolver()
export class UserResolver {
   @Mutation(() => UserResponse)
   async register(
       @Arg("options", () => UsernamePasswordInput) options: UsernamePasswordInput,
       @Ctx() {em, req}: MyContext

   ): Promise<UserResponse>{
       if(options.username.length <= 2)
       {
           return{
               errors: [{
                  field: 'username',
                  message: 'Length of user name must be greater than 2'
               }]
           }
       }
       if(options.password.length <= 2)
       {
           return{
               errors: [{
                  field: 'password',
                  message: 'Length of password must be greater than 2'
               }]
           }
       }
       const hashedPassword = await argon2.hash(options.password);
       let user;
        try{
            const result = await (em as EntityManager)
            .createQueryBuilder(User)
            .getKnexQuery()
            .insert({
                    username: options.username,
                    password: hashedPassword,
                    created_at: new Date(),
                    updated_at: new Date()
                })
                .returning("*");  
                user = result[0];        
        }
        catch(err){
            if(err.detail.includes("already exists")){
               return {
                   errors: [{
                    field: 'username',
                    message: 'User name already exists ',
                   }]
               }      
            }
            
        }
        
        req.session.userId = user.id;

        return {user};
   }
}

Below is the code for my Entity

import { Entity, PrimaryKey, Property } from "@mikro-orm/core";
import { Field,  ObjectType } from "type-graphql";

@ObjectType()
@Entity()
export class User {
  @Field()
  @PrimaryKey()
  id!: number;

  @Field(() => String)
  @Property({type: "date"})
  createdAt = new Date();

  @Field(() => String)
  @Property({ type: "date", onUpdate: () => new Date() })
  updatedAt = new Date();

  @Field()
  @Property({ type: "text", unique: true})
  username!: string;

  @Property({ type: "text"})
  password!: string;
  
}

Solution

  • in order to fix the issue, you may need to update declaration from

    mutation($options: UsernamePasswordInput){
    

    to

    mutation($options: UsernamePasswordInput!){
    

    then update graphql as below:

     mutation Register($options: UsernamePasswordInput!) {
        register(options: $options) {
        // you may change the format below
        errors {
            ...
        }
        user {
        ...
        }
      }
    }
    

    Finally, you may call it from frontend like below:

    const response = await register({ options: value });
    

    Please note that you may need to call graphql codegen to generate useRegisterMutation hook to make the above code to work in Formik form.