Búsqueda de sitios web

typescript - Mejor práctica para columnas virtuales (calculadas) en Nest.js + TypeORM + OpenApi


Tengo una entidad (imagen) que tiene una propiedad calculada (ruta de la imagen) así:

@Entity()
export class Image extends BaseEntity {
  @PrimaryGeneratedColumn()
  @IsInt()
  id: number

  @Column({ type: 'varchar', length: 255, unique: true })
  @IsString()
  @IsNotEmpty()
  uid: string

  protected mainPath: string

  @AfterLoad()
  @AfterInsert()
  @AfterUpdate()
  generateMainPath(): void {
    this.mainPath = Math.floor(this.id / 10000) + '/' + Math.floor(this.id / 100) + '/' + this.uid
  }
}

Uso mainPath para almacenar imágenes en el sistema de archivos del back-end, y también lo envío al front-end para construir la ruta de img src. mainPath se generó con éxito y se envió al cliente.

El problema es que el front-end usa swagger (nswag openapi2tsclient) generado en un archivo TypeScript construido sobre el esquema OpenAPI, generado por Nest.JS. No hay una propiedad mainPath para la interfaz IImage en el archivo generado. ¿Es posible declararla de alguna manera para que esté definida en el cliente y se llene con el valor proporcionado desde la respuesta ajax?

P.D.1. Intenté decorar mainPath con @ApiProperty({ type: String }) - no ayudó.

P.D.2. Traté de usar @Column({ type: virtual }) pero el back-end luego da una advertencia de que este tipo no es compatible con MySQL.

P.D.3. Parece que mainPath debería declararse como una propiedad usual no calculada en el front-end, ya que se rellenará previamente con los datos del back-end (no se calculará en el front-end).

P.S.4. La forma posible parece ser usar modelos simples para la base de datos y la clase ExtendedImage que tiene la propiedad mainPath calculada en el constructor si no se proporciona. ¿Es esto la mejor práctica?

Respuesta #1

Pude obtener lo que quería usando algunos decoradores de class-validator. No sé por qué funciona:

@Entity()
export class Image extends BaseEntity {
  @PrimaryGeneratedColumn()
  @IsInt()
  id: number

  @Column({ type: 'varchar', length: 255, unique: true })
  @IsString()
  @IsNotEmpty()
  uid: string

  @IsString()
  @IsOptional()
  protected mainPath: string

  @AfterLoad()
  @AfterInsert()
  @AfterUpdate()
  generateMainPath(): void {
    this.mainPath = Math.floor(this.id / 10000) + '/' + Math.floor(this.id / 100) + '/' + this.uid
  }

Artículos relacionados