Недавно я перешел от использования typegraphql и typeorm напрямую к их использованию сnesjs. В основном это был прямой опыт. Однако у меня есть одна проблема в отношении перечислений.
У меня есть набор пользовательских декораторов, которые я объединил вместе, чтобы я мог легко украшать свои модели, не имея декораторов 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)
}
}
Мой декоратор @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
...
Моя база данных возвращает числовые идентификаторы для перечислений, а тип поля в базе данных (mysql) — enum
. В качестве примера, когда моя база данных возвращает 1 для accountState, который должен быть ПРИОСТАНОВЛЕН, я получаю ошибку 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+), так что это просто что-то конкретное с перечислениями.
Это главный блокатор для меня, и любая помощь будет очень признательна, поскольку в настоящее время у меня нет идей.
Изменить. В ответ на Шуссон, когда я добавляю декораторы вручную, это также не работает:
@Column({
default: AccountState.ACTIVE,
enum: AccountState,
type: 'enum',
})
@Field(type => AccountState)
public accountState: AccountState
Ваше здоровье, отметка
Я обновил свой вопрос, спасибо за ваш ответ @shusson
В конце концов я исправил это, сделав перечисления равными их строковым эквивалентам, а не числовым значениям по умолчанию при их определении следующим образом:
export enum AccountState {
ACTIVE='ACTIVE',
SUSPENDED='SUSPENDED',
CLOSED='CLOSED',
}
Это приводит к сохранению строкового значения в базе данных, что хорошо работает с graphql. Это определенно работало раньше, я не уверен, как :) Я бы предпочел использовать числовые значения с точки зрения дизайна БД, поэтому любые идеи все равно будут оценены.
Ты классный парень. Я только что пропустил registerEnumType(), я использовал строку Enums, однако она не работала, я видел твой код и БАМ... Я понял подсказку... В моем случае перечисление с Числовое значение также работает. Просто объявите документ мангуста, используя интерфейс с перечислением int.
Спасибо, рад, что смог быть полезен :)
я использую декоратор @Field в пакете nestjs/graphql. Попытался установить значение по умолчанию как массив, содержащий элемент перечисления... площадка graphql выдала ошибку с указанием "each value in ... must be a valid enum value"
. Только после того, как член enum был установлен равным его строковому эквиваленту, больше не было ошибки... Ваше решение помогло решить мою проблему. Спасибо.
Вы пытались заменить пользовательский декоратор enum стандартным объявлением typeorm?