如何使用配置对象和依赖关系创建NestJs管道?

时间:2020-06-23 03:27:04

标签: nestjs

我想将配置字符串传递给Pipe,但也想注入服务。 NesJs文档描述了如何做到彼此独立但又不能相互独立的两者。请看以下示例:

pipe.ts

@Injectable()
export class FileExistsPipe implements PipeTransform {

  constructor(private filePath: string, db: DatabaseService) { }

  async transform(value: any, metadata: ArgumentMetadata) {
    const path = value[this.filePath];
    const doesExist =  await this.db.file(path).exists()
    if(!doesExist)  throw new BadRequestException();
    return value;
  }
}

controller.ts

@Controller('transcode')
export class TranscodeController {

  @Post()
  async transcode ( 
    @Body( new FileExistsPipe('input')) transcodeRequest: JobRequest) {
    return await this.videoProducer.addJob(transcodeRequest);
  }

基本上,我希望能够将属性名称传递给我的管道(例如'input'),然后让管道在请求中查找属性的值(例如const path = value[this.filePath]),然后然后查看该文件在数据库中是否存在。如果不是,则抛出Bad Request错误,否则继续。

我面临的问题是我需要NestJ来注入我的DataBaseService。对于当前示例,它不会,并且我的IDE给我一个错误,提示new FileExistsPipe('input')仅传递了一个参数,但期望传递两个参数(例如DatabaseService)。

反正有实现这一目标的方法吗?

1 个答案:

答案 0 :(得分:1)

编辑:我刚刚检查了您的仓库(很抱歉之前没有找到它)。您的DatabaseServiceundefined中的FIleExistPipe,因为您使用了AppController中的管道。 AppController将在解决DatabaseModule之前解决。如果要在forwardRef()中使用管道,则可以使用DatabaseServiceAppController注入管道中。最好的做法是在功能模块中提供功能控制器。

export const FileExistPipe: (filePath: string) => PipeTransform = memoize(
  createFileExistPipe
);

function createFileExistPipe(filePath: string): Type<PipeTransform> {
  class MixinFileExistPipe implements PipeTransform {
    constructor(
      // use forwardRef here
      @Inject(forwardRef(() => DatabaseService)) private db: DatabaseService 
    ) {
      console.log(db);
    }

    async transform(value: ITranscodeRequest, metadata: ArgumentMetadata) {
      console.log(filePath, this.db);
      const doesExist = await this.db.checkFileExists(filePath);
      if (!doesExist) throw new BadRequestException();
      return value;
    }
  }

  return mixin(MixinFileExistPipe);
}

您可以使用Mixin来实现。您无需导出injectable类,而可以导出将返回此类的工厂函数。

export const FileExistPipe: (filePath: string) => PipeTransform = memoize(createFileExistPipe);

function createFileExistPipe(filePath: string) {
    class MixinFileExistPipe implements PipeTransform {
        constructor(private db: DatabaseService) {}
        ...
    }

    return mixin(MixinFileExistPipe);
}
  1. memoize只是一个简单的函数,用于使用filePath缓存创建的mixin-pipe。因此,对于每个filePath,您只有一个版本的管道。
  2. mixin是从nestjs/common导入的帮助函数,它将包装MixinFileExistPipe类并使DI容器可用(以便可以注入DatabaseService)。

用法:

@Controller('transcode')
export class TranscodeController {

@Post()
async transcode (
    // notice, there's no "new"
    @Body(FileExistsPipe('input')) transcodeRequest: JobRequest) {
    return await this.videoProducer.addJob(transcodeRequest);
}
  1. mixin后卫注入了MongoDB连接 a mixin guard injecting the MongoDB Connection
  2. 控制台显示正在记录的连接 the console shows the connection being logged