typescriptnestjstypeormnestjs-typeormnestjs-swagger

Nest.JS with TypeORM How to entity member Buffer type casting?


export class ReadUserDto {
  @IsULID()
  @ApiProperty({
    example: '01J3Z772NCBMD9BETHBMB74HBW',
    description: 'User ULID',
  })
  userId: string;
  }
}

DTO's ULID member is string class like this.

@Entity('users', { schema: 'DB' })
export class Users {
  @ApiProperty({
    example: '01J3Z772NCBMD9BETHBMB74HBW',
    description: 'User ULID',
  })
  @Column('binary', { primary: true, name: 'user_id', length: 16 })
  userId: Buffer;
}

But the entity's ULID member is Buffer class.

I want to use ULID as string class in services.

How and where to add type casting layer for solve this problem simply and quiet less duplicate code?

I tried add method convert to entity class in DTO class. But it violates DTO must not have logical method rule. and it happens to uncomportable use mapped-types.

Or tried to use transform decorator with class-validator. but it always returns null... So I found lots of questions, but there's no example recommend code for class-validator before use transform. Only option is use two validation Pipes, but someone says It does not work as you want.


Solution

  • If you don't need to use the Buffer-typed value on the entity, you could make it also a string, and specify a transformer: in the column options, to convert the TS value to/from a raw database type right in the entity class:

    class UlidTransformer implements ValueTransformer {
      to(value: string): Buffer {
        return Buffer.from(value);
      }
    
      from(value: Buffer): string {
        return value.toString();
      }
    }
    
    
    @Entity('users', { schema: 'DB' })
    export class Users {
      @ApiProperty({
        example: '01J3Z772NCBMD9BETHBMB74HBW',
        description: 'User ULID',
      })
      @Column('binary', { primary: true, name: 'user_id', length: 16, transformer: new UlidTransformer() })
      userId: string;
    

    Your idea with class-transformer is also possible to implement, but you'd have to manually call the transformation between the DTO and the entity class -- Nest's validation pipe on its own only applies validations & transformations on the controller method inputs.