ParseObjectIdPipe для идентификатора объекта MongoDB

Я хочу создать NestJs API с TypeORM и MongoDB. Поля моего идентификатора объекта относятся к типу ObjectID. Маршруты контроллера должны проверять входящие идентификаторы перед их передачей службам. Я знаю, что Nest поставляется с ParseIntPipe и ParseUUIDPipe, но, насколько мне известно, я ничего не могу использовать для MongoDB ObjectID.

Поэтому я создал свой собственный канал для этих полей, как описано здесь https://docs.nestjs.com/pipes#transformation-use-case

import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
import { ObjectID } from 'typeorm';

@Injectable()
export class ParseObjectIdPipe implements PipeTransform<any, ObjectID> {
  transform(value: any): ObjectID {
    const validObjectId: boolean = ObjectID.isValid(value);

    if (validObjectId) {
      throw new BadRequestException('Invalid ObjectId');
    }

    const objectId: ObjectID = ObjectID.createFromHexString(value);
    return objectId;
  }
}

и надеюсь, что это поможет даже в крайних случаях. Я могу использовать его для параметров маршрута, например

  @Get(':id')
  public getUserById(@Param('id', ParseObjectIdPipe) id: ObjectID): Promise<User> {
    return this.usersService.getUserById(id);
  }

У меня проблема в том, что некоторые маршруты нуждаются в Body валидации. Я использую пакет class-validator, как описано здесь

https://docs.nestjs.com/techniques/validation

Кажется, мне нужно создать свой собственный декоратор валидатора класса для этих ObjectID полей, но это должно быть нормально. Возможно, я найду здесь что-нибудь о том, как это сделать https://github.com/typestack/class-validator#custom-validation-classes. Но как мне преобразовать эти поля в тип ObjectID? Могу ли я использовать для этого и кастомную трубу позже?


Обновление:

Я также попытался преобразовать значение с помощью пакета class-transformer. Итак, код для этого

import { ObjectID } from 'typeorm';
import { Type, Transform } from 'class-transformer';
import { BadRequestException } from '@nestjs/common';

export class FooDTO {
  @Type(() => ObjectID)
  @Transform(bar => {
    if (ObjectID.isValid(bar)) {
      throw new BadRequestException('Invalid ObjectId');
    }

    return ObjectID.createFromHexString(bar);
  })
  public bar: ObjectID;
}

К сожалению, значение bar всегда равно undefined. Но, возможно, этот код может помочь в целях проверки и преобразования ...


person hrp8sfH4xQ4    schedule 19.02.2020    source источник


Ответы (4)


Я взял ваш код и изменил некоторые части. Протестировал, работает нормально.

import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
import { Types } from 'mongoose';

@Injectable()
export class ParseObjectIdPipe implements PipeTransform<any, Types.ObjectId> {
    transform(value: any): Types.ObjectId {
        const validObjectId = Types.ObjectId.isValid(value);

        if (!validObjectId) {
            throw new BadRequestException('Invalid ObjectId');
        }

        return Types.ObjectId.createFromHexString(value);
    }
}
person sh park    schedule 24.12.2020
comment
Если ваши изменения устранили проблему, укажите, что это были за изменения. Как бы то ни было, ваш ответ выглядит как комментарий, а не как ответ. - person Danny Varod; 24.12.2020

Итак, для проверки Body я могу использовать декоратор IsMongoId() отсюда

https://github.com/typestack/class-validator#manual-validation

Проверка будет выглядеть так

import { IsMongoId } from 'class-validator';
import { ObjectID } from 'typeorm';

export class FooDTO {
  @IsMongoId()
  public bar: ObjectID;
}
person hrp8sfH4xQ4    schedule 20.02.2020

Вы получаете undefined, потому что вы импортируете из неправильной библиотеки. вам нужно изменить это:

import { ObjectID } from 'typeorm';

для этого:

import { ObjectID } from 'mongodb';
person Hugo    schedule 10.08.2020

Для подхода класса-трансформера это сработало для меня

import { IsNotEmpty } from "class-validator";
import { Type, Transform } from 'class-transformer';
import { Types } from "mongoose"

export class CreateCommentDto {

    @IsNotEmpty()
    @Type(() => Types.ObjectId)
    @Transform(toMongoObjectId)
    articleId: Types.ObjectId

с этим определением для 'toMongoObjectId':

export function toMongoObjectId({ value, key }): Types.ObjectId {
    if ( Types.ObjectId.isValid(value) && ( Types.ObjectId(value).toString() === value)) {
        return Types.ObjectId(value);
    } else {
        throw new BadRequestException(`${key} is not a valid MongoId`);
    }
}
person Andrés Cruz    schedule 25.06.2021