typescript - NestJS DTO-klasse angi kjørerekkefølge for class-validator og class-transformer


Finnes det en måte å angi kjørerekkefølgen for dekoratører når man beskriver en DTO-klasse i NestJS ved bruk av class-validator og class-transformer-pakkene?

Følgende kode feiler når verdien av foo settes til null med feilen:

Forventet en streng, men mottok null

@IsOptional()
@IsString()
@IsByteLength(1, 2048)
@Transform(({ value }) => validator.trim(value))
@Transform(({ value }) => validator.stripLow(value))
foo: string;

Selv om jeg har en isString-dekorator som skal sjekke at det faktisk ble sendt en streng og allerede må feile for å ikke overføre utførelsen til @Transform-dekoratorene, så feilet den ikke.

Svar #1

Class-Validator fungerer basert på klasser. Forespørselsdata som kommer inn til serveren er bare vanlige JSON-objekter til å begynne med. For å endre denne oppførselen, må Nest først kalle plainToClass fra class-validator hvis du bruker dens ValidationPipe. På grunn av dette, får @Transform()-dekoratørene forrang over de andre class-validator-dekoratørene, og blir behandlet først. Du kan omgå dette ved å bruke flere pipes, eller muligens ved å gi standardverdier til @Transform()-dekoratøren, men det som skjer er den tilsiktede effekten.

Svar #2

Kontroller @Transfrom og Validator-dekoratørens utførelsesrekkefølge med 2 ValidationPipe

main.ts

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
    }),

    new ValidationPipe({
      transform: true,
      transformOptions: { groups: ['transform'] },
    }),
  );

  await app.listen(4000);
}
bootstrap();

create-user.dto.ts

export class CreateUserDto {
  @ApiProperty({
    description: 'username',
    minLength: 4,
    maxLength: 64,
  })
  @Length(4, 64)
  name: string;

  @ApiProperty({
    description: 'password',
    minLength: 4,
    maxLength: 64,
  })
  @Length(6, 64)
  @Transform(({ value }: { value: string }) => hashSync(value), {
    groups: ['transform'],
  })
  password: string;
}

Dette vil kjøre @Length først, og deretter @Transform.

Oversettelse med Deepl

Relaterte artikler