【问题标题】:Type Graphql custom Resolver类型 Graphql 自定义解析器
【发布时间】:2020-10-04 06:10:05
【问题描述】:

我有一个用户 ObjectType 并希望在我的 LoginResolver 中将用户和为该用户生成的令牌作为对象返回,如下所示:

{user:User, token:string} 目前我可以返回用户或字符串,具体取决于我在 @Mutation() 装饰器中给出的类型

@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;
  }

当我尝试创建一个 UserWIthToken 对象类型时,用户实体上的每个字段都会出现以下错误:

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

【问题讨论】:

    标签: node.js typescript graphql apollo-server typegraphql


    【解决方案1】:

    您需要为这种情况创建一个自定义的 ObjectType

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

    然后在查询中使用该对象而不是用户

    @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
        };
    }
    

    请注意,我在这里使用了@Query 而不是@Mutation,因为它更适合这种情况,根据经验,如果您想在不修改数据的情况下读取数据,请使用查询,否则删除/添加/编辑数据使用突变。

    然后你可以像这样运行登录查询

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

    【讨论】:

    • 谢谢你的回复,我更新了问题,还是有一些错误
    • 您似乎是在尝试直接从UserWithToken 对象查询用户字段,我更新了有关如何正确查询用户数据的答案。
    • 啊对,我没有相应地更新查询谢谢:)
    • 有可能,例如tokenRepo.createToken 可以在 db 的列中写入时间戳来记录上次发布日期,所以在这种情况下最好使用突变。同样从客户端的角度来看,当我们通过查询发出令牌时,这意味着 apollo 可以使用缓存值,而对于突变,它将始终被执行。
    • 谢谢@MichałLytek 我从来没有想过这种情况!
    猜你喜欢
    • 2018-03-18
    • 1970-01-01
    • 2021-12-22
    • 2021-01-23
    • 2019-09-29
    • 2019-09-07
    • 2020-07-21
    • 2020-02-21
    • 2016-10-21
    相关资源
    最近更新 更多