Coder Social home page Coder Social logo

nestjs-typegoose's Introduction

nestjs-typegoose

NPM npm version Build Status Coverage Status

Description

Injects typegoose models for nest components and controllers. Typegoose equivalant for @nestjs/mongoose.

Using Typegoose removes the need for having a Model interface.

Installation

npm install --save nestjs-typegoose

Basic usage

You can checkout the example project for more details.

app.module.ts

import { Module } from "@nestjs/common";
import { TypegooseModule } from "nestjs-typegoose";
import { CatsModule } from "./cat.module.ts";

@Module({
  imports: [
    TypegooseModule.forRoot("mongodb://localhost:27017/nest", {
      useNewUrlParser: true
    }),
    CatsModule
  ]
})
export class ApplicationModule {}

Create class that describes your schema

cat.model.ts

import { prop } from "@typegoose/typegoose";
import { IsString } from "class-validator";

export class Cat {
  @IsString()
  @prop({ required: true })
  name: string;
}

Inject Cat for CatsModule

cat.module.ts

import { Module } from "@nestjs/common";
import { TypegooseModule } from "nestjs-typegoose";
import { Cat } from "./cat.model";
import { CatsController } from "./cats.controller";
import { CatsService } from "./cats.service";

@Module({
  imports: [TypegooseModule.forFeature([Cat])],
  controllers: [CatsController],
  providers: [CatsService]
})
export class CatsModule {}

Get the cat model in a service

cats.service.ts

import { Injectable } from "@nestjs/common";
import { InjectModel } from "nestjs-typegoose";
import { Cat } from "./cat.model";
import { ReturnModelType } from "@typegoose/typegoose";

@Injectable()
export class CatsService {
  constructor(
    @InjectModel(Cat) private readonly catModel: ReturnModelType<typeof Cat>
  ) {}

  async create(createCatDto: { name: string }): Promise<Cat> {
    const createdCat = new this.catModel(createCatDto);
    return await createdCat.save();
  }

  async findAll(): Promise<Cat[] | null> {
    return await this.catModel.find().exec();
  }
}

Finally, use the service in a controller!

cats.controller.ts

import { Controller, Get, Post, Body } from "@nestjs/common";
import { CatsService } from "./cats.service";
import { Cat } from "./cats.model.ts";

@Controller("cats")
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Get()
  async getCats(): Promise<Cat[] | null> {
    return await this.catsService.findAll();
  }

  @Post()
  async create(@Body() cat: Cat): Promise<Cat> {
    return await this.catsService.create(cat);
  }
}

Mongoose Schema Options

To add custom mongoose schema options you can simply change Typegoose.forFeature to the following format:

@Module({
  imports: [
    TypegooseModule.forFeature([
      {
        typegooseClass: Cat,
        schemaOptions: {
          collection: "ADifferentCollectionNameForCats"
        }
      }
    ])
  ]
})
export class CatsModule {}

Mongoose Discriminators

To add discriminators to a model, you may specify a discriminators array in the long-form options shown above.

You may either add just the class, or if you need to override the discriminator key value, an object with typegooseClass and discriminatorId property.

For example:

class Tabby extends Cat {
  @prop()
  spotted: boolean 
}

class BlackCat extends Cat {
  @prop()
  unlucky: boolean
}

@Module({
  imports: [
    TypegooseModule.forFeature([
      {
        typegooseClass: Cat,
        discriminators: [
          Tabby,
          {
            typegooseClass: BlackCat,
            discriminatorId: 'Black'
          }
        ]
      }
    ])
  ]
})
export class CatsModule {}

Async Mongoose Schema Options

To provide asynchronous mongoose schema options (similar to nestjs mongoose implementation) you can use the TypegooseModule.forRootAsync

@Module({
  imports: [
    TypegooseModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        uri: configService.getString("MONGODB_URI")
        // ...typegooseOptions (Note: config is spread with the uri)
      }),
      inject: [ConfigService]
    })
  ]
})
export class CatsModule {}

Note: typegooseOptions with async

The typegooseOptions is spread with the uri. The uri is required!

You can also use a class with useClass

import {
  TypegooseOptionsFactory,
  TypegooseModuleOptions
} from "nestjs-typegoose";

class TypegooseConfigService extends TypegooseOptionsFactory {
  createTypegooseOptions():
    | Promise<TypegooseModuleOptions>
    | TypegooseModuleOptions {
    return {
      uri: "mongodb://localhost/nest"
    };
  }
}

@Module({
  imports: [
    TypegooseModule.forAsyncRoot({
      useClass: TypegooseConfigService
    })
  ]
})
export class CatsModule {}

Or if you want to prevent creating another TypegooseConfigService class and want to use it from another imported module then use useExisting

@Module({
  imports: [
    TypegooseModule.forAsyncRoot({
      imports: [ConfigModule],
      useExisting: ConfigService
    })
  ]
})
export class CatsModule {}

Multiple MongoDB Connections

To have multiple mongoDB connections one needs to add a connectionName string to forRoot and forFeature.

app.module.ts

import { Module } from "@nestjs/common";
import { TypegooseModule } from "nestjs-typegoose";

@Module({
  imports: [
    TypegooseModule.forRoot("mongodb://localhost:27017/otherdb", {
      useNewUrlParser: true,
      connctionName: "other-mongodb"
    }),
    CatsModule
  ]
})
export class ApplicationModule {}

cat.module.ts

@Module({
  imports: [TypegooseModule.forFeature([Cat], "other-mongodb")],
  controllers: [CatsController],
  providers: [CatsService]
})
export class CatsModule {}

And for forAsyncRoot add connectionName to the options as well.

@Module({
  imports: [
    TypegooseModule.forAsyncRoot({
      connectionName: "other-mongodb",
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        uri: configService.getString("MONGODB_URI"),
        connectionName: config
        // ...typegooseOptions (Note: config is spread with the uri)
      }),
      inject: [ConfigService]
    })
  ]
})
export class CatsModule {}

Testing

Like @nestjs/mongoose (see the testing section) nestjs-typegoose's forFeature and forRoot rely on a database connection to work. To unit test your CatService without connecting to a mongo database you need to create a fake model using a custom provider.

import { getModelToken } from "nestjs-typegoose";

...

@Module({
  ProductService,
  {
    provide: getModelToken('Product'),
    useValue: fakeProductModel
  }
})

In a spec file this would look like:

const module: TestingModule = await Test.createTestingModule({
  providers: [
    {
      provide: getModelToken("Product"),
      useValue: productModel
    },
    ProductService
  ]
}).compile();

The string given to getModelToken function should be the class name of the typegoose model that you are testing.

FAQ


Q: 'useNewUrlParser' does not exist in type 'TypegooseConnectionOptions'

A: Make sure that you have the typings for mongoose installed. npm install --save-dev @types/mongoose


Requirements

  1. @typegoose/typegoose +6.1.5
  2. @nestjs/common +6.10.1
  3. @nestjs/core +6.10.1
  4. mongoose (with typings @types/mongoose) +5.7.12

License

nestjs-typegoose is MIT licensed.

nestjs-typegoose's People

Contributors

kpfromer avatar hasezoey avatar goodluckhf avatar beaulac avatar mmv08 avatar duro avatar cheerlesscloud avatar dirkbolte avatar colinc-zylotech avatar decrn avatar luisvt avatar lafeuil avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.