枚举不适用于 nestjs 和 graphql
Enums not working with nestjs and graphql
我最近从直接使用 typegraphql 和 typeorm 转变为将它们与 nestjs 一起使用。大多数情况下,这是一个简单的体验。然而,我有一个关于枚举的问题。
我有一组组合在一起的自定义装饰器,这样我就可以轻松地装饰我的模型,而无需同时使用 typeorm、typegraphql 和 class 验证器装饰器。这在以前工作得很好,现在在除枚举以外的所有情况下都工作得很好。
这里的例子是 @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)
}
}
我的@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)
}
}
我在单独的文件中定义枚举,如下所示:
import { registerEnumType } from 'type-graphql'
export enum AccountState {
ACTIVE,
SUSPENDED,
CLOSED,
}
registerEnumType(AccountState, { name: 'AccountState' })
并这样使用:
@EntityType()
export class Member extends VersionedEntity {
@IdentifierNewGuid()
public readonly id: string
@Enum(type => AccountState, { default: AccountState.ACTIVE })
public accountState: AccountState
...
我的数据库返回枚举的数字 ID,数据库中的字段类型 (mysql) 是 enum
。例如,我的数据库为应该暂停的 accountState 返回 1,我收到一个 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
因此,回顾一下这种方法直接与 typeorm 和 typegraphql 一起使用效果很好,但遗憾的是现在无法使用。我用过的所有其他装饰器似乎都可以正常工作(50+),所以它只是枚举特有的东西。
这对我来说是一个主要障碍,任何帮助将不胜感激,因为我目前没有想法。
编辑 - 作为对 Shusson 的回应,当我手动添加装饰器时它实际上也不起作用:
@Column({
default: AccountState.ACTIVE,
enum: AccountState,
type: 'enum',
})
@Field(type => AccountState)
public accountState: AccountState
干杯,
马克
最后我通过使枚举等于它们的字符串等价物而不是像这样定义它们时的默认数值来解决这个问题:
export enum AccountState {
ACTIVE='ACTIVE',
SUSPENDED='SUSPENDED',
CLOSED='CLOSED',
}
这导致将字符串值存储在数据库中,而不是与 graphql 一起使用。这以前肯定有效,我不确定如何:)我更愿意从数据库设计的角度使用数值,所以任何想法仍然会受到赞赏。
我最近从直接使用 typegraphql 和 typeorm 转变为将它们与 nestjs 一起使用。大多数情况下,这是一个简单的体验。然而,我有一个关于枚举的问题。
我有一组组合在一起的自定义装饰器,这样我就可以轻松地装饰我的模型,而无需同时使用 typeorm、typegraphql 和 class 验证器装饰器。这在以前工作得很好,现在在除枚举以外的所有情况下都工作得很好。
这里的例子是 @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)
}
}
我的@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)
}
}
我在单独的文件中定义枚举,如下所示:
import { registerEnumType } from 'type-graphql'
export enum AccountState {
ACTIVE,
SUSPENDED,
CLOSED,
}
registerEnumType(AccountState, { name: 'AccountState' })
并这样使用:
@EntityType()
export class Member extends VersionedEntity {
@IdentifierNewGuid()
public readonly id: string
@Enum(type => AccountState, { default: AccountState.ACTIVE })
public accountState: AccountState
...
我的数据库返回枚举的数字 ID,数据库中的字段类型 (mysql) 是 enum
。例如,我的数据库为应该暂停的 accountState 返回 1,我收到一个 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
因此,回顾一下这种方法直接与 typeorm 和 typegraphql 一起使用效果很好,但遗憾的是现在无法使用。我用过的所有其他装饰器似乎都可以正常工作(50+),所以它只是枚举特有的东西。
这对我来说是一个主要障碍,任何帮助将不胜感激,因为我目前没有想法。
编辑 - 作为对 Shusson 的回应,当我手动添加装饰器时它实际上也不起作用:
@Column({
default: AccountState.ACTIVE,
enum: AccountState,
type: 'enum',
})
@Field(type => AccountState)
public accountState: AccountState
干杯, 马克
最后我通过使枚举等于它们的字符串等价物而不是像这样定义它们时的默认数值来解决这个问题:
export enum AccountState {
ACTIVE='ACTIVE',
SUSPENDED='SUSPENDED',
CLOSED='CLOSED',
}
这导致将字符串值存储在数据库中,而不是与 graphql 一起使用。这以前肯定有效,我不确定如何:)我更愿意从数据库设计的角度使用数值,所以任何想法仍然会受到赞赏。