NestJS was first developed in January 2017.1, and the first official release was released in July 2017.5. It is an Express based backend framework developed in TypeScript. At the beginning of the design, it was mainly used to solve the architectural problems of developing Node.js applications. It was inspired by Angular. In this article, I’ll outline some of the highlights in NestJS.
Component container
NestJS uses a component container, where each component is decoupled from other components. When a component depends on another component, it needs to specify node dependencies to be used:
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
import { OtherModule } from '.. /OtherModule';
@Module({
imports: [OtherModule],
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {}
Copy the code
Dependency Injection (DI)
Like Angular, it uses the dependency injection design pattern for development
When you use an object, the DI container already creates it for you, without having to manually instantiate it, for decoupling purposes:
// Create a service
@Inject(a)export class TestService {
public find() {
return 'hello world'; }}// Create a controller
@Controller(a)export class TestController {
controller(
private readonly testService: TestService
) {}
@Get(a)public findInfo() {
return this.testService.find()
}
}
Copy the code
To make the TestController use the TestService service, write as provider when creating the Module:
@Module({
controllers: [TestController],
providers: [TestService],
})
export class TestModule {}
Copy the code
Of course, you can Inject any class with @Inject() into the Module for use by the Module’s Controller or Service.
The implementation behind this is based on Decorator + Reflect Metadata. See typescript-Reflect Metadata for more details.
Fine-grained Middleware
With Express, we use a variety of middleware, such as logging services, timeout interception, permission validation, and so on. In NestJS, Middleware functions are divided into Middleware, Filters, Pipes, Grards, and Interceptors.
For example, use Filters to catch errors thrown by processing applications:
@Catch(a)export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: any, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const status = exception.getStatus();
// Something else to do, such as using logs
response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(), path: request.url, }); }}Copy the code
Use the interceptor to intercept response data and return it in the format {data: T} :
import { Injectable, NestInterceptor, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export interface Response<T> {
data: T;
}
@Injectable(a)export class TransformInterceptor<T>
implements NestInterceptor<T, Response<T>> {
intercept(
context: ExecutionContext,
call$: Observable<T>,
): Observable<Response<T>> {
return call$.pipe(map(data= >({ data }))); }}Copy the code
Using Guards, return 401 when there is no ‘admin’ role:
import { ReflectMetadata } from '@nestjs/common';
export const Roles = (. roles:string[]) = > ReflectMetadata('roles', roles);
@Post(a)@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
Copy the code
Data validation
Thanks to class-Validator and class-Transformer, validation of incoming parameters becomes very simple:
/ / create a Dto
export class ContentDto {
@IsString()
text: string
}
@Controller(a)export class TestController {
controller(
private readonly testService: TestService
) {}
@Get(a)public findInfo(
@Param() param: ContentDto / / use
) {
return this.testService.find()
}
}
Copy the code
A 400 error occurs when text is not a string.
GraphQL
GraphQL, developed by Facebook, is considered a revolutionary API tool because it allows clients to specify the data they want in a request, rather than being pre-defined on the back end like traditional REST.
NestJS wraps Apollo Server to make it easier to use in NestJS.
When using Apollo Server in Express:
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
// Construct a schema, using GraphQL schema language
const typeDefs = gql` type Query { hello: String } `;
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: (a)= > 'Hello world! ',}};const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
const port = 4000;
app.listen({ port }, () =>
console.log(`Server ready at http://localhost:${port}${server.graphqlPath}`));Copy the code
Use it in NestJS:
// test.graphql
type Query {
hello: string;
}
// test.resolver.ts
@Resolver(a)export class {
@Query(a)public hello() {
return 'Hello wolrd'; }}Copy the code
Using a Decorator also looks more TypeScript.
other
In addition to the above enumeration, NestJS implements microservice development, TypeORM, and Prisma features, which are not covered here.
reference
- Learn more about typescript-Reflect Metadata
- Egg VS NestJS
- NestJS website