NestJS is a progressive Node.js framework written in TypeScript that combines OOP (object-oriented programming), FP (functional programming), and FRP (functional response programming) concepts. NestJS is very similar in design to the front-end Angular framework and the back-end Spring framework, making it easy to learn in five minutes.

Create a project

Install the NestJS command-line tool:

npm install -g @nestjs/cli
# or
yarn global add @nestjs/cli @nestjs/schematics
Copy the code

Create a new project and start it:

nest new xxx
yarn run start:dev # Start the project and open http://localhost:3000/ to see Hello World
Copy the code

The main code is generated in the SRC directory:

├ ─ ─ app. Controller. Ts# controller├ ─ ─ app. The module. Ts# root module├ ─ ─ app. Service. Ts# service└ ─ ─ the main ts# Project entry, you can choose platform, configure middleware, etc
Copy the code

The dependencies between them are:

Import file main.ts

Main.js creates the application with the built-in NestFactory:

async function bootstrap() {
  const app = await NestFactory.create(AppModule)
  await app.listen(3000)
}
bootstrap()
Copy the code

App root module. The module. Ts

Modules are classes decorated with @Module(). NestJS uses it to organize applications, and each NestJS application has at least one module, the root module:

@Module({
  imports: [],
  controllers: [AppController, ArticleController, FileController],
  providers: [AppService, ArticleService]
})
export class AppModule {}
Copy the code

The controller app. Controller. Ts

The controller is responsible for responding to client requests and returning data.

import { Controller, Get } from '@nestjs/common'
import { AppService } from './app.service'

@Controller(a)export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello()
  }
}
Copy the code

As you can see, the Controller is just a class decorated with the @Controller() decorator. Adding a controller to NestJS is simple, such as creating an article controller:

nest g controller article # will be generated article/article. Controller. Ts file
Copy the code

Methods can be added inside the controller, for example:

  1. list()Method represents a list of articles
  2. detail()Method represents the details of the article
import { Controller, Get } from '@nestjs/common'

@Controller('article')
export class ArticleController {
  @Get('list')
  list() {
    return ['the article 1'.'the article 2']}@Get('detail')
  detail() {
    return 'Article Details'}}Copy the code

These @get (‘list’) and @get (‘detail’) are called method decorators, and the list() method is called when the user requests /article/list, and the detail() method is called when the user requests /article/detail.

Service app. Service. Ts

The service in NestJS plays the role of Model in MVC architecture, which is responsible for dealing with the database for the controller to call.

import { Injectable } from '@nestjs/common'

@Injectable(a)export class AppService {
  getHello(): string {
    return 'Hello World! '}}Copy the code

As you can see, the service is essentially a class decorated with @Injectable() that can be injected into any controller. The command to add a service in NestJS is:

nest g service article
Copy the code

Connecting to a Database

API interface is ready, just the connection data this part, here uses MongoDB as an example, of course, can also use other databases such as MySQL, etc., the use method can refer to the official document. Install the dependencies first:

yarn add @nestjs/mongoose mongoose
Copy the code

Then create a Schemas directory to place the database model:

import { Schema } from 'mongoose'
const ArticleSchema = new Schema(
  {
    title: { type: String }, // Title of the article
    content: { type: String }, // The content of the article
    cover: { type: String }, // Article cover
  },
  { timestamps: true})export { ArticleSchema }
Copy the code

Then introduce the model in app.module.ts and establish the connection:

import { MongooseModule } from '@nestjs/mongoose'
import { ArticleSchema } from './schemas/article.schema'
@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost:27017/api'),
    MongooseModule.forFeature([{ name: 'article', schema: ArticleSchema }])
  ],
  controllers: [AppController, ArticleController],
  providers: [AppService, ArticleService]
})
export class AppModule {}
Copy the code

We can then inject the article model into the Controller or service to implement the add, delete, change and query logic:

@Injectable() export class ArticleService { constructor(@InjectModel('article') private articleModel) {} find() { return  this.articleModel.find({}).lean() } }Copy the code

Advanced features

Once you have mastered the concepts of Module, Controller, and Service, as well as the way to connect to the database, you can start your development project. Of course, there are also some advanced usage, you can continue to read.

The interceptor

Interceptors, as the name implies, are used as interceptors, which means that some additional logic can be added before entering the Controller and after the controller handles it. For example, here we define a pre-interceptor:

@Injectable(a)export class MyInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const req = context.switchToHttp().getRequest()
    const query = req.query
    const data = req.body
    // Validate query or body, throw an error if not valid
    return next.handle().pipe(
      map(data= > {
        // To process the returned data, use tap if you don't want to affect the returned value
        return newData
      })
    )
  }
}
Copy the code

File upload

Handling file uploads in NestJS is very easy, and the following example allows the back end to get the files passed from the front end:

import { Controller, Post, UseInterceptors, UploadedFile, UploadedFiles, Body } from '@nestjs/common'
import { FileInterceptor,FilesInterceptor } from '@nestjs/platform-express'

@Controller('files')
export class FileController {
  @Post('single')
  @UseInterceptors(FileInterceptor('file'))
  single(@UploadedFile() file, @Body() body) {
    console.log(file)
    console.log(body)
    return { ok: 1}}@Post('multiple')
  @UseInterceptors(FilesInterceptor('files'))
  multiple(@UploadedFiles() files, @Body() body) {
    console.log(files)
    console.log(body)
    return { ok: 1}}}Copy the code

The single interface is used to receive single files, and the multiple interface is used to receive multiple files, where the front end submits files to the back end with FormData.