Гнездо Js - DTO и сущности - PullRequest
       29

Гнездо Js - DTO и сущности

1 голос
/ 10 апреля 2020

Я пытаюсь разумно использовать DTO и Entities в своем проекте, но это кажется более сложным, чем могло бы быть. Я создаю бэкэнд для управления запасами, я использую Nest Js и TypeOrm.

Мой клиент отправляет мне набор данных, генерирует запрос POST, скажем:

{
  "length": 25,
  "quantity": 100,
  "connector_A": {
    "id": "9244e41c-9da7-45b4-a1e4-4498bb9de6de"
  },
  "connector_B": {
    "id": "48426cf0-de41-499b-9c02-94c224392448"
  },
  "category": {
    "id": "f961d67f-aea0-48a3-b298-b2f78be18f1f"
  }
}

Мой контроллер отвечает за проверку поля с помощью пользовательской ValidationPipe:

@Post()
  @UsePipes(new ValidationPipe())
  create(@Body() data: CableDto) {
    return this.cablesService.create(data);
}

Во многих местах я читал, что в лучших практиках данные RAW следует преобразовывать в DTO, а когда дело доходит до вставки данных, Я должен привести свой DTO к объекту typeOrm.

Я согласен с этим методом, но я нашел его очень сложным, даже более того, когда в нем есть связи между моими таблицами и префиксом существительным.

Вот мой Entity Cable

@Entity('t_cable')
export class Cable {

  @PrimaryGeneratedColumn('uuid')
  CAB_Id: string;

  @Column({
    type: "double"
  })
  CAB_Length: number;

  @Column({
    type: "int"
  })
  CAB_Quantity: number;

  @Column()
  CON_Id_A: string

  @Column()
  CON_Id_B: string

  @Column()
  CAT_Id: string

  @ManyToOne(type => Connector, connector => connector.CON_Id_A)
  @JoinColumn({ name: "CON_Id_A" })
  CON_A: Connector;

  @ManyToOne(type => Connector, connector => connector.CON_Id_B)
  @JoinColumn({ name: "CON_Id_B" })
  CON_B: Connector;

  @ManyToOne(type => Category, category => category.CAB_CAT_Id)
  @JoinColumn({ name: "CAT_Id" })
  CAT: Category;

}

А вот мой DTO для взаимодействия кабелей:

export class CableDto {

  id: string;

  @IsOptional()
  @IsPositive()
  @Max(1000)
  length: number;
  quantity: number;

  connector_A: ConnectorDto;
  connector_B: ConnectorDto;
  category: CategoryDto

  public static from(dto: Partial<CableDto>) {
    const it = new CableDto();
    it.id = dto.id;
    it.length = dto.length;
    it.quantity = dto.quantity;
    it.connector_A = dto.connector_A
    it.connector_B = dto.connector_B
    it.category = dto.category
    return it;
  }

  public static fromEntity(entity: Cable) {
    return this.from({
      id: entity.CAB_Id,
      length: entity.CAB_Length,
      quantity: entity.CAB_Quantity,
      connector_A: ConnectorDto.fromEntity(entity.CON_A),
      connector_B: ConnectorDto.fromEntity(entity.CON_B),
       category: CategoryDto.fromEntity(entity.CAT)
    });
  }

  public static toEntity(dto: Partial<CableDto>) {
    const it = new Cable();
    if (dto.hasOwnProperty('length')) {
      it.CAB_Length = dto.length;
    }
    if (dto.hasOwnProperty('quantity')) {
      it.CAB_Quantity = dto.quantity;
    }
    if (dto.hasOwnProperty('connector_A')) {
      it.CON_Id_A = dto.connector_A.id;
    }
    if (dto.hasOwnProperty('connector_B')) {
      it.CON_Id_B = dto.connector_B.id;
    }
    if (dto.hasOwnProperty('category')) {
      it.CAT_Id = dto.category.id;
    }
    return it;
  }
}

Я знаю, что эти три метода для преобразования в обоих направлениях DTOs и Entites чувствует довольно грязный, вот почему я здесь ..

Мой сервис для простого запроса на создание или получение знает:

async create(dto: CableDto): Promise<CableDto> {
  const cable = await this.cablesRepository.save(CableDto.toEntity(dto));
  return await this.findById(cable.CAB_Id)
}

Я убежден, что для этого есть более простое решение, или в л Восток правильный способ сделать это.

Есть идеи?

Спасибо.

1 Ответ

0 голосов
/ 14 апреля 2020

Для всех преобразований типов (например, DTO> сущность или сущность> DTO) я разработал библиотеку metamorphosis-nest js, чтобы упростить преобразования объектов.
Добавляет в Nest JS отсутствующая концепция службы инъекционного преобразования для всех конверсий, предоставляемых вашими конвертерами, которые ранее были зарегистрированы в сервисе конвертации (например, сервис конвертации, предоставляемый Spring Framework в Java приложении).

Так что в вашем случае , с typerORM:

  1. npm install --save @fabio.formosa/metamorphosis-nest
    
  2. import { MetamorphosisNestModule } from '@fabio.formosa/metamorphosis-nest';
    
    @Module({
      imports: [MetamorphosisModule.register()],
      ...
    }
    export class MyApp{ }
    
  3. import { Convert, Converter } from '@fabio.formosa/metamorphosis';
    
    @Injectable()
    @Convert(CableDto, Cable)
    export default class CableDtoToCableConverter implements Converter<CableDto, Promise<Cable>> {
    
    constructor(private readonly connection: Connection){}
    
    public async convert(source: CableDto): Promise<Cable> {
      const cableRepository: Repository<Cable> = this.connection.getRepository(Cable);
      const target: Product | undefined = await cableRepository.findOne(source.id);
      if(!target)
        throw new Error(`not found any cable by id ${source.id}`);
      target.CAB_Length = source.length;
      target.CAB_Quantity = source.quantity;
      ... and so on ...
      return target;
    }
    

}

Наконец, вы можете внедрить и использовать Conversion Service как хотите:

 const cable = <Cable> await this.convertionService.convert(cableDto, Cable);

Конвертер из Cable в CableDto более прост.

Получите README , чтобы найти примеры и все преимущества гнездо метаморфоза js.

...