枚举不适用于 nestjs 和 graphql

Tre*_*360 10 enums graphql typeorm nestjs typegraphql

我最近从直接使用 typegraphql 和 typeorm 转向将它们与 nestjs 一起使用。大多数情况下,这是一次直接的体验。然而,我有一个关于枚举的问题。

我有一组组合在一起的自定义装饰器,这样我就可以轻松地装饰我的模型,而无需同时使用 typeorm、typegraphql 和类验证器装饰器。这以前很好用,现在在除枚举以外的所有情况下都很好用。

作为一个例子,这里是一个@OptionalDecimal 装饰器:

import { IsNumber } from 'class-validator'
import { Field, Float } from 'type-graphql'
import { Column } from 'typeorm'

export function OptionalDecimal() {
    const typeDecorator = IsNumber()
    const fieldDecorator = Field(type => Float, { nullable: true })
    const columnDecorator = Column('decimal', { nullable: true })

    return (target: any, key: string) => {
        typeDecorator(target, key)
        fieldDecorator(target, key)
        columnDecorator(target, key)
    }
}
Run Code Online (Sandbox Code Playgroud)

我的@Enum 装饰器是这样的:

import { IsEnum } from 'class-validator'
import { Field } from 'type-graphql'
import { Column } from 'typeorm'
import { IEnumOptions } from './IEnumOptions'

export function Enum(
    typeFunction: (type?: any) => object,
    options: IEnumOptions = {}
) {
    const isEnumDecorator = IsEnum(typeFunction())
    const fieldDecorator = Field(typeFunction)
    const columnDecorator = Column({
        default: options.default,
        enum: typeFunction(),
        type: 'enum',
    })

    return (target: any, key: string) => {
        isEnumDecorator(target, key)
        fieldDecorator(target, key)
        columnDecorator(target, key)
    }
}
Run Code Online (Sandbox Code Playgroud)

我在单独的文件中定义我的枚举,如下所示:

import { registerEnumType } from 'type-graphql'

export enum AccountState {
  ACTIVE,
  SUSPENDED,
  CLOSED,
}

registerEnumType(AccountState, { name: 'AccountState' })
Run Code Online (Sandbox Code Playgroud)

并因此使用:

@EntityType()
export class Member extends VersionedEntity {
  @IdentifierNewGuid()
  public readonly id: string

  @Enum(type => AccountState, { default: AccountState.ACTIVE })
  public accountState: AccountState
...
Run Code Online (Sandbox Code Playgroud)

我的数据库正在返回枚举的数字 ID,数据库 (mysql) 中的字段类型是enum. 作为一个例子,我的数据库为 accountState 返回 1 应该是 SUSPENDED 我收到一个 graphql 错误:

  "errors": [
    {
      "message": "Expected a value of type \"AccountState\" but received: 1",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ],
      "path": [
        "searchMembers",
        0,
        "accountState"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: Expected a value of type \"AccountState\" but received: 1",
            "    at completeLeafValue
Run Code Online (Sandbox Code Playgroud)

因此,回顾一下这种方法直接与 typeorm 和 typegraphql 一起工作得很好,但遗憾的是现在无法工作。我所使用的所有其他装饰器似乎都工作正常(50+),所以它只是与枚举相关的东西。

这对我来说是一个主要的障碍,任何帮助将不胜感激,因为我目前没有想法。

编辑 - 作为对 Shusson 的回应,当我手动添加装饰器时,它实际上也不起作用:

@Column({
    default: AccountState.ACTIVE,
    enum: AccountState,
    type: 'enum',
  })
@Field(type => AccountState)
public accountState: AccountState
Run Code Online (Sandbox Code Playgroud)

干杯,马克

Tre*_*360 7

最后,我通过使枚举等于它们的字符串等效项而不是默认数值来解决这个问题,就像这样定义它们:

export enum AccountState {
  ACTIVE='ACTIVE',
  SUSPENDED='SUSPENDED',
  CLOSED='CLOSED',
}
Run Code Online (Sandbox Code Playgroud)

这导致将字符串值存储在数据库中,而不是与 graphql 一起使用。这在之前肯定有效,我不确定如何:) 我更喜欢从数据库设计的角度使用数值,所以任何想法仍然会受到赞赏。