Search code examples
node.jstypescriptgraphqlapollo-servertypegraphql

Type Graphql custom Resolver


Iam have a User ObjectType and want in my LoginResolver, to return the user and a generated token for that user as an Object like so:

{user:User, token:string} Currently I can return either the User OR a string, depending on the Type i give in the @Mutation() decorator

@Mutation((returns) => User)
  async login(
    @Arg("email") email: string,
    @Arg("password") password: string,
    @Ctx("ctx") ctx: IContext
  ) {
    const user = await this.userRepo.findOneUser({ where: { email } });
    const success = await compare(password, user.password);
    if (!success) ctx.throw(401);
    const token = await this.tokenRepo.createToken(user);

    return user;
  }

when i try creating an UserWIthToken Objecttype I get the following Error for every field on the user entity:

app_1       |   error: [ValidationError: Cannot query field "id" on type "UserWithToken".] {
app_1       |     locations: [ [Object] ],
app_1       |     path: undefined,
app_1       |     extensions: { code: 'GRAPHQL_VALIDATION_FAILED', exception: [Object] }
app_1       |   }
app_1       | }```
dont mind the app_1 here, Iam using docker

Solution

  • You need to create a custom ObjectType for this case

    @ObjectType()
    class UserWithToken {
        @Field(() => User)
        user: User
          
        @Field()
        token: string
    }
    

    Then use that object in your query instead of user

    @Query((returns) => UserWithToken)
    async login(
        @Arg("email") email: string,
        @Arg("password") password: string,
        @Ctx("ctx") ctx: IContext
    ) : Promise<UserWithToken> {
        const user = await this.userRepo.findOneUser({ where: { email } });
        const success = await compare(password, user.password);
        if (!success) ctx.throw(401);
        const token = await this.tokenRepo.createToken(user);
    
        return {
            user,
            token
        };
    }
    

    Please note I used @Query here instead of @Mutation as it fit this case better, as a rule of thumb if you want to read data without modifying it, use Query, other wise for deleting/adding/editing data use Mutation.

    Then you can run the login query like this

    query {
      login(email: "xx@xx.com", password: "xxxxx") {
        token
        user {
          id
          name
          email
          ...
        }
      }
    }