简体   繁体   English

带有 MongoDB 和 NestJsxAutomapper 的 NestJS 导致错误“无法读取未定义的属性插件”

[英]NestJS with MongoDB and NestJsxAutomapper resulting in error 'cannot read property plugin of undefined'

I am working on an API with NestJS, and because I have DTO's I am using an AutoMapper (made by @nartc and/or nestjsx), I have tried to make my example as small as I could with the Foo example, because I use multiple files.我正在使用 NestJS 开发一个 API,因为我有 DTO,所以我正在使用 AutoMapper(由@nartc 和/或 nestjsx 制作),我试图让我的示例尽可能小,因为我使用Foo示例多个文件。

This is my module:这是我的模块:

// foo.module.ts
import { Module } from "@nestjs/common";
import { MongooseModule } from "@nestjs/mongoose";

import { Foo, FooSchema } from "./foo.entity.ts";
import { FooController } from "./foo.controller.ts";
import { FooService } from "./foo.service.ts";
import { FooProfile } from "./foo.profile.ts";

@Module({
  imports: [
    MongooseModule.forFeature([
      {
        name: Foo.name,
        schema: FooSchema,
        collection: "foos",
      }
    ])
    // FooProfile <-- if I uncomment this, the program will give the error (shown at the bottom of this question)
  ],
  controllers: [FooController],
  providers: [FooProivder],
})
export class FooModule {}

This is my entity:这是我的实体:

// foo.entity.ts
import { Schema, SchemaFactory, Prop } from "@nestjs/mongoose";
import { Document } from "mongoose";

@Schema()
export class Foo extends Document { // if I remove the `extends Document` it works just fine
  @Prop({ required: true })
  name: string;
  @Prop()
  age: number
}

export const FooSchema = SchemaFactory.createForClass(Foo);

This is my DTO:这是我的 DTO:

// foo.dto.ts
export class FooDTO {
  name: string;
}

This is my controller:这是我的 controller:

// foo.controller.ts
import { Controller, Get } from "@nestjs/common";
import { InjectMapper, AutoMapper } from "nestjsx-automapper";

import { Foo } from "./foo.entity";
import { FooService } from "./foo.service";
import { FooDTO } from "./dto/foo.dto";

@Controller("foos")
export class FooController {
  constructor(
    private readonly fooService: FooService
    @InjectMapper() private readonly mapper: AutoMapper
  ) {}

  @Get()
  async findAll() {
    const foos = await this.fooService.findAll();
    const mappedFoos = this.mapper.mapArray(foos, Foo, FooDTO);
    // ^^ this throws an error of the profile being undefined (duh)
    return mappedFoos;
  }
}

This is my profile:这是我的个人资料:

// foo.profile.ts
import { Profile, ProfileBase, InjectMapper, AutoMapper } from "nestjsx-automapper";

import { Foo } from "./foo.entity";
import { FooDTO } from "./foo.dto";

@Profile()
export class FooProfile extends ProfileBase {
  constructor(@InjectMapper() private readonly mapper: AutoMapper) {
    // I've read somewhere that the `@InjectMapper() private readonly` part isn't needed,
    // but if I exclude that, it doesn't get the mapper instance. (mapper will be undefined)
    super();
    this.mapper.createMap(Foo, FooDTO);
  }
}

If I uncomment the line I highlighted in the module, it will result in the following error..如果我取消注释我在模块中突出显示的行,将导致以下错误。

[Nest] 11360   - 2020-08-18 15:53:06   [ExceptionHandler] Cannot read property 'plugin' of undefined +1ms
TypeError: Cannot read property 'plugin' of undefined
    at Foo.Document.$__setSchema ($MYPATH\node_modules\mongoose\lib\document.js:2883:10)
    at new Document ($MYPATH\node_modules\mongoose\lib\document.js:82:10)
    at new Foo($MYPATH\dist\foo\foo.entity.js:15:17)

I have also referred to this answer on stackoverflow , but that doesn't work for me either.我也在stackoverflow 上提到了这个答案,但这对我也不起作用。 I have also combined that with the documentation , but with no luck.. How would I get the AutoMapper to register my profiles?我还将它与文档结合起来,但没有运气。我如何让 AutoMapper 注册我的配置文件?

Update更新

The error seems to originate from the foo entity, if I remove the extends Document and the Schema() , Prop({... }) from the class it works fine, it seems like I have to inject mongoose or something?该错误似乎源自 foo 实体,如果我从 class 中删除extends DocumentSchema()Prop({... })它工作正常,似乎我必须注入 mongoose 或其他东西?

In your module, just import the path to the profile like below:在您的模块中,只需将路径导入配置文件,如下所示:

import 'relative/path/to/foo.profile';

By importing the path to file, TypeScript will include the file in the bundle and then the @Profile() decorator will be executed.通过导入文件路径, TypeScript会将文件包含在包中,然后执行@Profile()装饰器。 When @Profile() is executed, AutoMapperModule keeps track of all the Profiles then when it's turn for NestJS to initialize AutoMapperModule (with withMapper() method), AutoMapperModule will automatically add the Profiles to the Mapper instance.当执行@Profile()时, AutoMapperModule会跟踪所有的Profiles ,然后当轮到 NestJS 初始化AutoMapperModule (使用withMapper()方法)时, AutoMapperModule会自动将 Profile 添加到 Mapper 实例。

With that said, in your FooProfile 's constructor, you'll get AutoMapper instance that this profile will be added to话虽如此,在您的FooProfile的构造函数中,您将获得此配置文件将添加到的AutoMapper实例

@Profile()
export class FooProfile extends ProfileBase {
   // this is the correct syntax. You would only need private/public access modifier
   // if you're not going to use this.mapper outside of the constructor
   // You DON'T need @InjectMapper() because that's Dependency Injection of NestJS. 
   // Profile isn't a part of NestJS's DI
   constructor(mapper: AutoMapper) {

   }
}

The above answer will solve your problems with AutoMapper .以上答案将解决您使用AutoMapper的问题。 As far as your Mongoose problem, I would need a sample repro to tell for sure.至于你的 Mongoose 问题,我需要一个示例 repro 来确定。 And also, visit our Discord for this kind of question.还有,访问我们的 Discord 咨询此类问题。

What worked for me.什么对我有用。

1. Updated all the absolute paths for models, schemas, entities (is easy if you search for from '/src in your projects, and update all the routes to relative paths) 1. 更新了模型、模式、实体的所有绝对路径(如果您在项目中搜索from '/src并将所有路由更新为相对路径,这很容易)

from: import { User } from 'src/app/auth/models/user/user.entity';来自: import { User } from 'src/app/auth/models/user/user.entity';

to: import { User } from './../../auth/models/user/user.entity';到: import { User } from './../../auth/models/user/user.entity';

2. mongoose imports: 2. mongoose进口:

from: import mongoose from 'mongoose';来自: import mongoose from 'mongoose';

to: import * as mongoose from 'mongoose';至: import * as mongoose from 'mongoose';

3. Remove validation pipe if you don't use it. 3.如果你不使用它,请删除验证pipe。 For some reason (I think i don't use them on the controller, I didn't investigate, I've removed from one controller the Validation Pipe) so If you have this try it:出于某种原因(我想我没有在 controller 上使用它们,我没有调查,我已经从一个 controller 中删除了验证管道)所以如果你有这个试试:

from:从:

@Controller('someroute')
@UsePipes(new ValidationPipe())
export class SomeController {}

to:到:

@Controller('someroute')
export class SomeController {}

I hope my solution worked for you ^_^我希望我的解决方案对你有用^_^

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM