Note: This is a previous Nest release announcement
🌟 Read about the latest release - NestJS version 9 here
Today I am excited to announce the official release of NestJS 7.
This is a major release spanning the entire platform, including the framework, numerous changes to the @nestjs/graphql
package, CLI improvements, and updated documentation.
In case you're not familiar with NestJS, it is a TypeScript Node.js framework that helps you build enterprise-grade efficient and scalable Node.js applications.
Photo by Stéphane Mingot
Last year was great for our community. In 2019, Nest has been recognised as the fastest-growing Node.js technology in the world. We've also made it to the TOP 20 GitHub repositories on the whole globe, and, according to NPM metrics, experienced an almost 400% growth in number of downloads on NPM, and thus becoming one of the most popular Node.js libraries with roughly 1 million of downloads each month! 2019 was amazing and we expect 2020 to be even better for the whole ecosystem!
What’s new?
This release brings lots of great features and long-awaited improvements. There are far too many to list here, but let’s take a high-level look at some of the most exciting ones.
GraphQL ❤️ TypeScript
In the version 6 major release of NestJS (announced here), we introduced the code first approach as a compatibility layer between the amazing type-graphql
package and the official @nestjs/graphql
module.
This allowed us to solve types redundancy problems by automatically generating GraphQL SDL from TypeScript metadata using decorators.
However, despite the numerous new opportunities that this integration has brought, we have faced many challenges that did not seem easily solvable down the road.
- The integration required developers to mix decorators coming from two different libraries.
If you've messed up the imports, all your resolvers would stop injecting dependencies through constructor (all of them would be equal to
undefined
). Thus, developers reported many bugs and issues, assuming that the integration doesn't work at all. - To generate a schema,
type-graphql
generatesresolve
function for each field. However, Nest has its own DI system that links dependencies and instantiates classes (in this case, providers), which methods are later being bounded to GraphQL fields. Hence, it led to unnecessary memory allocations. - Lastly, the code first approach requires using many additional decorators to define input types, args, etc. Initially, we decided to simply link to the external library documentation. However, the API of decorators which wrapped external decorators was somewhat different (because we must support schema first approach as well). We also didn't want to duplicate the documentation in the NestJS documentation because maintaining it would become impossible in the long run (adjusting to API changes, etc.).
So what did we do?
In order to future-proof the library to meet the needs of the community, we needed to reimplement all the features from scratch due to a lack of predictability and flexibility while dealing with the third party library.
To avoid lots of breaking changes, we did our best to make sure that the public API IS backwards-compatible.
Therefore, with a simple update: (search & replace) all the type-graphql
imports to use @nestjs/graphql
, and that's it. 🎊
import { Field, Int, ObjectType } from '@nestjs/graphql';import { Post } from './post';@ObjectType()export class Author { @Field((type) => Int) id: number; @Field({ nullable: true }) firstName?: string; @Field({ nullable: true }) lastName?: string; @Field((type) => [Post]) posts: Post[];}
Learn more about the code first approach here.
NestJS GraphQL Plugin
In addition, switching to our own Typescript & GraphQL implementation, allowed us to create a plugin (similar to the @nestjs/swagger
announced here).
To reduce the amount of boilerplate code required, Nest now provides a new GraphQL plugin (for code first applications) that enhances the TypeScript compilation process.
Hint This plugin is also opt-in. If you prefer, you can declare all decorators manually, or only specific decorators where you need them.
The new GraphQL plugin will automatically:
- annotate all input object (
@InputObject
), object type (@ObjectType
) and args (@Args
) classes properties with@Field
decorator unless@HideField
is used - set the
nullable
property depending on the question mark (e.g.name?: string
will setnullable: true
) - set the
type
property depending on the type (supports arrays as well)
Therefore, the example shown above can be rewritten as follows:
import { Field, Int, ObjectType } from '@nestjs/graphql';import { Post } from './post';@ObjectType()export class Author { @Field((type) => Int) id: number; firstName?: string; lastName?: string; posts: Post[];}
The plugin adds appropriate decorators on the fly based on the Abstract Syntax Tree.
TIP: You no longer have to struggle with
@Field
boilerplate decorators scattered throughout the entire project. They will be added automatically.
Learn how to enable the plugin here.
Flexible Custom Decorators
The custom decorators API has been unified for all types of applications. Now, whether you're creating a GraphQL application or a REST API, the factory passed into the createParamDecorator()
function will take the ExecutionContext
(read more here) object as a second argument.
import { createParamDecorator, ExecutionContext } from '@nestjs/common';export const User = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.user; });
Now, to determine the type of application that our decorator is currently evaluated, use the getType()
method:
const type = host.getType();if (type === 'http') { // HTTP application} else if (type === 'rpc') { // Microservice}
Improved Microservices
To enable the request-response message style, Nest creates two logical channels - one is responsible for transferring the data while the other waits for incoming responses.
For some underlying transports, such as NATS, this dual-channel support is provided out-of-the-box. For others, Nest compensates by manually creating separate channels.
Let's say that we have a single message handler @MessagePattern('getUsers')
.
In the past, Nest built two channels from this pattern: getUsers_ack
(for requests) and getUsers_res
(for responses).
With version 7, this naming scheme changes. Now Nest will build getUsers
channel (for requests) and getUsers.reply
(for responses) instead.
Also, specifically for the MQTT transport strategy, the response channel would be getUsers/reply
.
This change simplifies the integration with external systems, existing legacy applications, and also, allows avoiding clashes with wildcard subscriptions available in, for example, MQTT strategy.
Furthermore, the overall performance will improve. From now on, Nest will no longer send out redundant information as part of the message packets (in the request-response message style), hence, decreasing their size.
New Pipes
Nest v7 comes with 2 NEW pipes available out-of-the-box, respectively ParseBoolPipe
and ParseArrayPipe
(both exported from the @nestjs/common
package).
While ParseBoolPipe
is just another transformer pipe which along with the existing ParseIntPipe
can implicitly transform & validate values based on the expected type (read more here),
ParseArrayPipe
is a solution for sending either unwrapped or serialized arrays through the network.
Basically, TypeScript does not store metadata about generics or interfaces, so when you use them in your DTOs (Data Transfer Objects), ValidationPipe
may not be able to properly validate incoming data. For instance, the code below won't be correctly validated:
@Post()createBulk(@Body() createUserDtos: CreateUserDto[]) { return 'This action adds new users';}
Previously, to validate the array you had to create a dedicated class which contained a property that wraps the array.
Now, you can simply use the ParseArrayPipe
.
@Post()createBulk( @Body(new ParseArrayPipe({ items: CreateUserDto })) createUserDtos: CreateUserDto[],) { return 'This action adds new users';}
In addition, the ParseArrayPipe
may come in handy when parsing query parameters. Let's define the findByIds()
method that returns users based on identifiers passed as query parameters.
@Get()findByIds( @Query('id', new ParseArrayPipe({ items: Number, separator: ',' })) ids: number[],) { return 'This action return users by ids';}
And test this endpoint using cURL
:
$ # GET /?ids=1,2,3$ curl http://localhost:3000/?ids=1,2,3
The stringified ids
query parameter (ids=1,2,3
) will be automatically transformed to an array. In addition, each item will be validated and eventually, parsed to a number
.
Implicit type conversion
With the auto-transformation option enabled (transform: true
), the ValidationPipe
will now perform conversion of primitive types.
In the following example, the findOne()
method takes one argument which represents an extracted id
path parameter:
@Get(':id')findOne(@Param('id') id: number) { console.log(typeof id === 'number'); // true return 'This action returns a user';}
By default, every path parameter and query parameter comes over the network as a string
.
In the above example, we specified the id
type as a number
(in the method signature).
Therefore, the ValidationPipe
will try to automatically convert the string identifier to a number.
Documentation
Our official documentation has significant improvements to GraphQL section. We now cover most of features / functionalities you may need to get started with either schema first or code first approaches.
We strongly believe that this update will strongly improve the development experience. 🐈
Enterprise Consulting & Support
Our official NestJS Enterprise Consulting includes a broad range of services to empower your team.
We work alongside you to meet your deadlines while avoiding costly tech debt. Challenging issue? We've got you covered.
- Providing technical guidance & architectural reviews
- Mentoring team members
- Addressing security & performance concerns
- Performing in-depth code reviews
- Long-term support (LTS) & upgrade assistance
Our goal is to help you get to market faster. Nest core team members will help you utilize best practices and choose the right strategy for unique goals. You can learn more on the enterprise.nestjs.com.
Official NestJS Courses
We've recently launched a new website dedicated for the Official NestJS courses 📸 recorded by NestJS core team members.
With these courses, you'll learn everything about NestJS from the basic principles, best-practices, tips & tricks, to advanced patterns, getting you ready to build NestJS applications at any scale. 🚀
Sign up for the Nest newsletter right now and stay up do date with all the latest news. Everyone who signed up will be notificed once pre-order starts.
Migration from Nest 6
In order to migrate your existing project, follow the guidelines that are available here. Also, make sure to get rid of all deprecation messages that may appear in your console.
Support the NestJS Project
Nest is an MIT-licensed open source project with its ongoing development made possible thanks to the support by the community and our sponsors. Thank you!
<script>We strongly believe that someday we could fully focus on #opensource to make @nodejs world better 🚀🔥 @opencollect
— NestJS (@nestframework) April 25, 2018
👍 enjoy using @nestframework?
🙌 ask your company to support us:
🎁 https://t.co/taYS49lllr pic.twitter.com/L1O9Vf5uhS
This framework is a result of the long days, sleepless nights, and busy weekends. And we fully rely on the goodness ❤️ of the people. If you want to join them, you can read more here.
T-Shirts and hoodies
If you enjoy using NestJS and you would like to donate to our Open Source work (have your cake 🍰 and eat it), we just launched the official NestJS store 👕 where you can buy hoodies, T-shirts, and accessories!
Thank you
To all backers, sponsors, contributors, and community, thank you once again! This product is for you. And this is only the beginning of the long 🚀 story.
Become a Backer or Sponsor to Nest by donating to our open collective. ❤
Learn NestJS - Official NestJS Courses 📚
Level-up your NestJS and Node.js ecosystem skills in these incremental workshop-style courses, from the NestJS Creator himself, and help support the NestJS framework! 🐈🚀 The NestJS Fundamentals Course is now LIVE and 25% off for a limited time!
🎉 NEW - NestJS Course Extensions now live!
- NestJS Advanced Concepts Course now LIVE!
- NestJS Authentication / Authorization Course now LIVE!
- NestJS GraphQL Course (code-first & schema-first approaches) are now LIVE!
- NestJS Authentication / Authorization Course now LIVE!