Nest的第5版中新增了一个CLI命令,容许经过命令行生成项目和文件。 全局安装CLI:javascript
npm install -g @nestjs/cli
复制代码
或者经过Docker:java
docker pull nestjs/cli:[version]
复制代码
可使用如下命令生成新的Nest项目:node
nest new [project-name]
复制代码
此过程将询问 name, description, version (defaults to 0.0.0), and author (你的名字)。 完成此过程后,您将拥有一个设置好的Nest项目,其中依赖项安装在 node_modules 文件夹。 new 命令还会询问你想用什么包管理器,以一样的方式,有 yarn 或 npm 能够用。web
CLI中最经常使用的命令是 generate (g) 命令, 容许你建立新的 controllers, modules, servies 或Nest支持的任何其它组件:docker
class
(cl)controller
(co)decorator
(d)exception
(e)filter
(f)gateway
(ga)guard
(gu)interceptor
(i)middleware
(mi)module
(mo)pipe
(pi)provider
(pr)service
(s)括号中的字符串是该特定命令的别名 typescript
nest generate service [service-name]
复制代码
在控制台中,您能够输入:数据库
nest g s [service-name]
复制代码
最后,Nest CLI提供 info (i) 命令以显示项目的有关信息。这个命令将输出以下信息:npm
[System Information]
OS Version : macOS High Sierra
NodeJS Version : v8.9.0
YARN Version : 1.5.1
[Nest Information]
microservices version : 5.0.0
websockets version : 5.0.0
testing version : 5.0.0
common version : 5.0.0
core version : 5.0.0
复制代码
依赖注入是一种技术,它提供一个依赖对象,如一个模块或者一个组件,而后依赖的对象就像服务同样,能够把它注入到组件的构造函数中。 举个例子,在这里咱们将 UserRespository 服务注入到 UserService 的构造函数中, 从而提供从 UserService 组件内部访问User Database存储库的权限。编程
@Injectable()
export class UserService implements IUserService {
constructor(@Inject('UserRepository') private readonly UserRepository: typeof User) { }
...
}
复制代码
而后,这个 UsersService 将被注入到 UsersController,将提供控制器的路由对 UsersService 访问。后续章节中会介绍路由和依赖注入的更多信息。api
身份验证是开发过程当中最重要的方面之一。 做为开发人员,咱们始终但愿确保用户只能访问他们有权访问的资源。 近年来,身份验证方法已经扩展到变得更加复杂,但咱们仍然须要相同的服务器端逻辑,以确保这些通过身份验证的用户始终是合法用户,并将这种身份验证持久化,这样就不须要为每个 REST API 或 Websocket 的调用者从新进行身份验证,由于那将提供很是糟糕的用户体验。
Nest 选择集成Node.js生态系统中很是有名的认证库 Passport,同时使用JWT(JSON Web Token)策略。 Passport是在调用控制器上的端点以前传递HTTP调用的中间件。下面是为示例项目编写的 AuthenticationMiddleware ,它扩展了 NestMiddleware,根据请求有效负载中的电子邮件对每一个用户进行身份验证。
@Injectable()
export class AuthenticationMiddleware implements NestMiddleware {
constructor(private userService: UserService) { }
async resolve(strategy: string): Promise<ExpressMiddleware> {
return async (req, res, next) => {
return passport.authenticate(strategy, async (/*...*/args: any[]) => {
const [, payload, err] = args;
if (err) {
return res.status(HttpStatus.BAD_REQUEST).send('Unable to authenticate the user.');
}
const user = await this.userService.findOne({
where: { email: payload.email }
});
req.user = user;
return next();
})(req, res, next);
};
}
}
复制代码
Nest还实现了Guards,与其余提供程序同样,使用@Injectable()装饰器进行装饰。 Guards 能够控制用户能够访问的内容端点。 将在后续“身份验证”章节中更详细地讨论 Guards。
ORM是服务器和数据库之间通讯时最重要的概念之一:对象关系映射。 ORM提供内存中对象(诸如定义的 User 或 Comment 类) 和数据库中的关系表之间的映射。 容许您建立一个数据传输对象,该对象知道如何将存储在内存中的对象写入数据库,并将结果从SQL或其余查询语言读回内存。在这,咱们将讨论三种不一样的ORM: 两种关系型 orm 和一种针对 NoSQL 数据库的 orm。
TypeORM是Node.js中最成熟和最流行的ORM之一, Nest为其提供本身的包: @nestjs/typeorm,TypeORM很是强大,而且支持许多数据库,如MySQL,PostgreSQL,MariaDB,SQLite,MS SQL Server,Oracle和WebSQL。同时,Sequelize也是关系数据库的另外一个ORM。
若是TypeORM是最流行的ORM之一,那么Sequelize则是Node.js世界中最受欢迎的ORM之一。 它是用纯JavaScript编写的, 可是经过 sequelize-typescript 和 @types/sequelize 包进行了 TypeScript 绑定。Sequelize拥有强大的事务支持,关系,读取复制和更多功能。
最后一个ORM是处理非关系数据库或NoSQL数据库的ORM。mongoose 包处理MongoDB和JavaScript之间的对象关系。 与关系数据库相比,二者之间的实际映射关系要密切得多,由于MongoDB以JSON格式存储其数据,JSON格式表明JavaScript Object Notation。 Mongoose也有 @nestjs/mongoose ,并提供经过查询链查询数据库的能力。
REST是建立API的主要设计范例之一。它表明表明状态转移传输,并使用JSON做为传输格式,这与Nest存储对象的方式一致,所以它适合使用和返回 HTTP 调用。
客户端对服务器进行HTTP请求,服务器将根据URL和HTTP动词将调用路由到正确的Controller,可选择在到达Controller以前将其传递给一个或多个中间件。 而后,Controller将其交给service进行处理,其中可能包括经过ORM与数据库进行通讯。
若是客户端请求资源(GET请求),则返回一个可选主体; 若是是 POST/PUT/DELETE,则返回一个200 / 201 HTTP OK,若是没有响应主体。
Websocket 是从服务器链接和发送 / 接收数据的另外一种方式。
使用 websocket,客户端链接到服务器,而后订阅特定的通道。 而后,客户端能够将数据推送到订阅的通道。 服务器将接收此数据,而后将其广播到订阅该特定通道的每一个客户端。 这使得多个客户端均可以接收实时更新,而无需手动进行 API 调用。 大多数聊天应用程序使用WebSockets进行实时通讯,一旦其中一个成员发送消息,组消息中的每一个人都将收到消息。 与传统的请求-响应 API 相比,Websockets 容许更多的流式数据传输方法,由于 Websockets 能够在接收到数据时广播数据。
微服务容许将Nest将应用程序结构化为松散耦合服务的集合。 在Nest中,微服务略有不一样,由于它们是一个使用不一样于 HTTP 的传输层的应用程序。该层能够是TCP或Redis pub / sub等。
Nest支持TCP和Redis,但若是您与另外一个传输层结合,则可使用 CustomTransportStrategy 接口实现它。 微服务很棒,由于它们容许团队在全局项目中处理本身的服务,而且在不影响项目其他部分的状况下对服务进行更改,由于它是松散耦合的。 这使得持续交付和持续集成独立于其余团队的微服务。
正如咱们在上面看到的,REST 是设计 api 时的一种范例, 可是有一种新的方式来考虑建立和使用 api:GraphQL。
使用GraphQL,URL将接受带有JSON对象的查询参数,而不是每一个资源都有本身的URL指向。 此JSON对象定义要返回的数据的类型和格式。 Nest经过 @nestjs/graphql 包提供了这方面的功能。
这将包括项目中GraphQLModule, 它是Apollo服务器的包装器。
在讨论Web框架时,路由是核心之一。当客户端须要访问服务器的端点时, 这些端点中的每个都描述了如何检索/建立/操做存储在服务器上的数据。 描述API端点的每一个Component必须具备@Controller() 装饰器,用于描述该组件的端点集的 API 前缀。
@Controller('hello')
export class HelloWorldController {
@Get(‘world’)
printHelloWorld() {
return ‘Hello World’;
}
}
复制代码
@Module:项目中此可重用代码包的定义,它接受如下参数来定义其行为。
⋅⋅Imports:包含此模块中使用的组件。
⋅⋅Exports:导出模块。
⋅⋅Components:经过 Nest 注入的组件在这个模块上共享。
⋅⋅Controllers:在此模块中建立的控制器,这些控制器将根据定义的路由定义API端点。
复制代码
@Injectable:Nest中几乎全部东西都是能够经过构造函数注入的提供者。提供者用@Injectable()装饰。
..Middleware:在将请求传递给路由处理程序以前运行的函数。
..Interceptor:相似于中间件,它们在执行方法以前和以后绑定额外的逻辑,它们能够转换或彻底覆盖函数。拦截器的灵感来自面向方面编程(AOP)。
..Pipe:与拦截器功能的一部分相似,管道将输入数据转换为所需的输出。
..Guard:一个更聪明,更小众的中间件,Guards的惟一目的是肯定路由器处理程序是否应该处理请求。
..* Catch:告诉ExceptionFilter要查找的异常,而后将数据绑定到它。
复制代码
@Catch:将元数据绑定到异常过滤器,并告诉Nest过滤器只查找@Catch中列出的异常。
复制代码
在编写 Nest 服务器时,api文档是很是重要的,不然使用该 API 开发客户端的开发人员不知道发送什么或将获得什么。
最流行的文档引擎之一是 Swagger。 像其余模块同样,Nest 为 OpenAPI (Swagger) spec,提供了一个专用模块 @nestjs/swagger。
这个模块提供了装饰器来帮助描述 API 的输入 / 输出和端点。 而后能够经过服务器上的一个端点访问该文档。
命令查询责任分离(Command Query Responsibility Segregation,CQRS)的思想是,每一个方法要么是执行操做(Command)的方法,要么是执行请求数据(Query)的方法。
在咱们的示例应用程序的上下文中,不会在控制器中直接为一个端点建立数据库访问代码,而是建立一个组件(数据库服务) ,该组件具备getAllUsers()这样的方法,它将返回控制器服务能够调用的全部用户,从而将问题和答案分离到不一样的组件中。
测试你的 Nest 服务器将是必要的,确保部署时没有不可预见的安全性问题。
有两种不一样类型的测试: 单元测试和 E2E 测试(端到端测试)。 单元测试是测试小代码片断或代码块,它能够像测试单个函数或 Controller、 Interceptor 或任何其余Injectable测试同样精细。
如今有不少流行的单元测试框架,Jasmine 和 Jest 是两个流行的框架。 Nest 提供了特殊的包,@nestjs/testing,用于在 *.spec.ts 及 *.test.ts 类中编写单元测试。
E2E 测试是另外一种经常使用的测试形式,它不一样于单元测试,它测试整个功能,而不是测试单个功能或组件,而这正是端到端测试这个名称的来源。
当应用程序变得很是庞大,以致于很难绝对地测试每一段代码和端点。 在这种状况下,您可使用 E2E 测试从头至尾测试应用程序,以确保一切顺利进行。
对于 E2E 测试,Nest 应用程序能够再次使用 Jest 库来模拟组件。 除了 Jest 以外,还可使用 supertest 库来模拟 HTTP 请求。