Skip to content

Commit 76ee619

Browse files
Merge branch 'master' into feautre/recipes/necord
2 parents 658c0e5 + e8547ef commit 76ee619

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+3082
-1556
lines changed

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
18.14.0
1+
18.15.0

content/cli/scripts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The `nest` command is an OS level binary (i.e., runs from the OS command line).
1616

1717
#### Build
1818

19-
`nest build` is a wrapper on top of the standard `tsc` compiler (for [standard projects](https://docs.nestjs.com/cli/overview#project-structure)) or the webpack compiler (for [monorepos](https://docs.nestjs.com/cli/overview#project-structure)). It does not add any other compilation features or steps except for handling `tsconfig-paths` out of the box. The reason it exists is that most developers, especially when starting out with Nest, do not need to adjust compiler options (e.g., `tsconfig.json` file) which can sometimes be tricky.
19+
`nest build` is a wrapper on top of the standard `tsc` compiler (for [standard projects](https://docs.nestjs.com/cli/overview#project-structure)) or the webpack bundler using the `ts-loader` (for [monorepos](https://docs.nestjs.com/cli/overview#project-structure)). It does not add any other compilation features or steps except for handling `tsconfig-paths` out of the box. The reason it exists is that most developers, especially when starting out with Nest, do not need to adjust compiler options (e.g., `tsconfig.json` file) which can sometimes be tricky.
2020

2121
See the [nest build](https://docs.nestjs.com/cli/usages#nest-build) documentation for more details.
2222

content/devtools/ci-cd.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ To see reports, navigate to the project's corresponding page (see organizations)
5151

5252
<figure><img src="/assets/devtools/report.png" /></figure>
5353

54+
This is particularly helpful in identifying changes that may have gone unnoticed during code reviews. For instance, let's say someone has changed the scope of a **deeply nested provider**. This change might not be immediately obvious to the reviewer, but with Devtools, we can easily spot such changes and make sure that they're intentional. Or if we remove a guard from a specific endpoint, it will show up as affected in the report. Now if we didn't have integration or e2e tests for that route, we might not notice that it's no longer protected, and by the time we do, it could be too late.
55+
56+
Similarly, if we're working on a **large codebase** and we modify a module to be global, we'll see how many edges were added to the graph, and this - in most cases - is a sign that we're doing something wrong.
57+
5458
#### Build preview
5559

5660
For every published graph we can go back in time and preview how it looked before by clicking at the **Preview** button. Furthermore, if the report was generated, we should see the differences higlighted on our graph:
@@ -63,6 +67,8 @@ See screenshot below:
6367

6468
<figure><img src="/assets/devtools/nodes-selection.png" /></figure>
6569

70+
The ability to go back in time lets you investigate and troubleshoot the issue by comparing the current graph with the previous one. Depending on how you set things up, every pull request (or even every commit) will have a corresponding snapshot in the registry, so you can easily go back in time and see what changed. Think of Devtools as a Git but with an understanding of how Nest constructs your application graph, and with the ability to **visualize** it.
71+
6672
#### Integrations: Github Actions
6773

6874
First let's start from creating a new Github workflow in the `.github/workflows` directory in our project and call it, for example, `publish-graph.yml`. Inside this file, let's use the following definition:

content/devtools/overview.md

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Next up, let's install the required dependency:
2121
$ npm i @nestjs/devtools-integration
2222
```
2323

24-
> warning **Warning** If you're using `@nestjs/graphql` package in your application, make sure to install the upcoming `next` version (`npm i @nestjs/graphql@next`).
24+
> warning **Warning** If you're using `@nestjs/graphql` package in your application, make sure to install the latest version (`npm i @nestjs/graphql@11`).
2525
2626
With this dependency in place, let's open up the `app.module.ts` file and import the `DevtoolsModule` that we just installed:
2727

@@ -44,6 +44,8 @@ Once the `DevtoolsModule` is imported and your application is up and running (`n
4444

4545
<figure><img src="/assets/devtools/modules-graph.png" /></figure>
4646

47+
> info **Hint** As you can see on the screenshot above, every module connect to the `InternalCoreModule`. `InternalCoreModule` is a global module that is always imported into the root module. Since it's registered as a global node, Nest automatically creates edges between all of the modules and the `InternalCoreModule` node. Now, if you want to hide global modules from the graph, you can use the "Hide global modules" checkbox (in the sidebar).
48+
4749
So as we can see, `DevtoolsModule` makes your application expose an additional HTTP server (on port 8000) that the Devtools application will use to introspect your app.
4850

4951
Just to double-check that everything works as expected, change the graph view to "Classes". You should see the following screen:
@@ -56,45 +58,113 @@ To focus on a specific node, click on the rectangle and the graph will show a po
5658
5759
<figure><img src="/assets/devtools/node-popup.png" /></figure>
5860

61+
> info **Hint** To export a graph as an image, click on the **Export as PNG** button in the right corner of the graph.
62+
5963
Using the form controls located in the sidebar (on the left), you can control edges proximity to, for example, visualize a specific application sub-tree:
6064

6165
<figure><img src="/assets/devtools/subtree-view.png" /></figure>
6266

67+
This can be particularly useful when you have **new developers** on your team and you want to show them how your application is structured. You can also use this feature to visualize a specific module (e.g. `TasksModule`) and all of its dependencies, which can come in handy when you're breaking down a large application into smaller modules (for example, individual micro-services).
68+
69+
#### Investigating the "Cannot resolve dependency" error
70+
71+
> info **Note** This feature is supported for `@nestjs/core` >= `v9.3.10`.
72+
73+
Probably the most common error message you might have seen is about Nest not being able to resolve dependencies of a provider. Using Nest Devtools, you can effortlessly identify the issue and learn how to resolve it.
74+
75+
First, open up the `main.ts` file and update the `bootstrap()` call, as follows:
76+
77+
```typescript
78+
bootstrap().catch((err) => {
79+
fs.writeFileSync('graph.json', PartialGraphHost.toString() ?? '');
80+
process.exit(1);
81+
});
82+
```
83+
84+
Also, make sure to set the `abortOnError` to `false`:
85+
86+
```typescript
87+
const app = await NestFactory.create(AppModule, {
88+
snapshot: true,
89+
abortOnError: false, // <--- THIS
90+
});
91+
```
92+
93+
Now every time your application fails to bootstrap due to the **"Cannot resolve dependency"** error, you'll find the `graph.json` (that represents a partial graph) file in the root directory. You can then drag & drop this file into Devtools (make sure to switch the current mode from "Interactive" to "Preview"):
94+
95+
<figure><img src="/assets/devtools/drag-and-drop.png" /></figure>
96+
97+
Upon successful upload, you should see the following graph & dialog window:
98+
99+
<figure><img src="/assets/devtools/partial-graph-modules-view.png" /></figure>
100+
101+
As you can see, the highlighted `TasksModule` is the one we should look into. Also, in the dialog window you can already see some instructions on how to use fix this issue.
102+
103+
If we switch to the "Classes" view instead, that's what we'll see:
104+
105+
<figure><img src="/assets/devtools/partial-graph-classes-view.png" /></figure>
106+
107+
This graph illustrates that the `DiagnosticsService` which we want to inject into the `TasksService` was not found in the context of the `TasksModule` module, and we should likely just import the `DiagnosticsModule` into the `TasksModule` module to fix this up!
108+
63109
#### Routes explorer
64110

65111
When you navigate to the **Routes explorer** page, you should see all of the registered entrypoints:
66112

67113
<figure><img src="/assets/devtools/routes.png" /></figure>
68114

115+
> info **Hint** This page shows not only HTTP routes, but also all of the other entrypoints (e.g. WebSockets, gRPC, GraphQL resolvers etc.).
116+
117+
Entrypoints are grouped by their host controllers. You can also use the search bar to find a specific entrypoint.
118+
119+
If you click on a specific entrypoint, **a flow graph** will be displayed. This graph shows the execution flow of the entrypoint (e.g. guards, interceptors, pipes, etc. bound to this route). This is particularly useful when you want to understand how the request/response cycle looks for a specific route, or when troubleshooting why a specific guard/interceptor/pipe is not being executed.
120+
69121
#### Sandbox
70122

71123
To execute JavaScript code on the fly & interact with your application in real-time, navigate to the **Sandbox** page:
72124

73125
<figure><img src="/assets/devtools/sandbox.png" /></figure>
74126

127+
The playground can be used to test and debug API endpoints in **real-time**, allowing developers to quickly identify and fix issues without using, for example, an HTTP client. We can also bypass the authentication layer, and so we no longer need that extra step of logging in, or even a special user account for testing purposes. For event-driven applications, we can also trigger events directly from the playground, and see how the application reacts to them.
128+
129+
Anything that gets logged down is streamlined to the playground's console, so we can easily see what's going on.
130+
131+
Just execute the code **on the fly** and see the results instantly, without having to rebuild the application and restart the server.
132+
133+
<figure><img src="/assets/devtools/sandbox-table.png" /></figure>
134+
135+
> info **Hint** To pretty display an array of objects, use the `console.table()` (or just `table()`) function.
136+
75137
#### Bootstrap performance analyzer
76138

77139
To see a list of all class nodes (controllers, providers, enhancers, etc.) and their corresponding instantiation times, navigate to the **Bootstrap performance** page:
78140

79141
<figure><img src="/assets/devtools/bootstrap-performance.png" /></figure>
80142

143+
This page is particularly useful when you want to identify the slowest parts of your application's bootstrap process (e.g. when you want to optimize the application's startup time which is crucial for, for example, serverless environments).
144+
81145
#### Audit
82146

83147
To see the auto-generated audit - errors/warnings/hints that the application came up with while analyzing your serialized graph, navigate to the **Audit** page:
84148

85149
<figure><img src="/assets/devtools/audit.png" /></figure>
86150

151+
> info **Hint** The screenshot above doesn't show all of the available audit rules.
152+
153+
This page comes in handy when you want to identify potential issues in your application.
154+
87155
#### Preview static files
88156

89157
To save a serialized graph to a file, use the following code:
90158

91159
```typescript
92160
await app.listen(3000); // OR await app.init()
93-
writeFileSync('./graph.json', app.get(SerializedGraph).toString());
161+
fs.writeFileSync('./graph.json', app.get(SerializedGraph).toString());
94162
```
95163

96164
> info **Hint** `SerializedGraph` is exported from the `@nestjs/core` package.
97165
98166
Then you can drag and drop this/upload this file:
99167

100168
<figure><img src="/assets/devtools/drag-and-drop.png" /></figure>
169+
170+
This is helpful when you want to share your graph with someone else (e.g., co-worker), or when you want to analyze it offline.

content/discover/who-uses.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@
198198
{
199199
"logo": "/assets/logo/amplication.svg",
200200
"url": "https://amplication.com"
201+
},
202+
{
203+
"logo": "/assets/logo/hingehealth.png",
204+
"url": "https://hingehealth.com",
205+
"width": "120px"
201206
}
202207
],
203208
"Body": [

content/faq/errors.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ During your development with NestJS, you may encounter various errors as you lea
44

55
#### "Cannot resolve dependency" error
66

7+
> info **Hint** Check out the [NestJS Devtools](/devtools/overview#investigating-the-cannot-resolve-dependency-error) which can help you resolve the "Cannot resolve dependency" error effortlessly.
8+
79
Probably the most common error message is about Nest not being able to resolve dependencies of a provider. The error message usually looks something like this:
810

911
```bash
@@ -30,6 +32,8 @@ If the `<unknown_token>` above is the string `Object`, it means that you're inje
3032
3133
Also, make sure you didn't end up injecting the provider on itself because self-injections are not allowed in NestJS. When this happens, `<unknown_token>` will likely be equal to `<provider>`.
3234

35+
<app-banner-devtools></app-banner-devtools>
36+
3337
If you are in a **monorepo setup**, you may face the same error as above but for core provider called `ModuleRef` as a `<unknown_token>`:
3438

3539
```bash

content/faq/global-prefix.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ Alternatively, you can specify route as a string (it will apply to every request
2020
```typescript
2121
app.setGlobalPrefix('v1', { exclude: ['cats'] });
2222
```
23+
24+
> info **Hint** The `path` property supports wildcard parameters using the [path-to-regexp](https://github.com/pillarjs/path-to-regexp#parameters) package. Note: this does not accept wildcard asterisks `*`. Instead, you must use parameters (e.g., `(.*)`, `:splat*`).

content/faq/hybrid-application.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A hybrid application is one that both listens for HTTP requests, as well as make
44

55
```typescript
66
const app = await NestFactory.create(AppModule);
7-
const microservice = app.connectMicroservice({
7+
const microservice = app.connectMicroservice<MicroserviceOptions>({
88
transport: Transport.TCP,
99
});
1010

@@ -71,7 +71,7 @@ By default a hybrid application will not inherit global pipes, interceptors, gua
7171
To inherit these configuration properties from the main application, set the `inheritAppConfig` property in the second argument (an optional options object) of the `connectMicroservice()` call, as follow:
7272

7373
```typescript
74-
const microservice = app.connectMicroservice(
74+
const microservice = app.connectMicroservice<MicroserviceOptions>(
7575
{
7676
transport: Transport.TCP,
7777
},

content/faq/raw-body.md

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ One of the most common use-case for having access to the raw request body is per
99
First enable the option when creating your Nest Express application:
1010

1111
```typescript
12-
const app = await NestFactory.create(AppModule, {
12+
import { NestFactory } from '@nestjs/core';
13+
import type { NestExpressApplication } from '@nestjs/platform-express';
14+
import { AppModule } from './app.module';
15+
16+
// in the "bootstrap" function
17+
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
1318
rawBody: true,
1419
});
1520
await app.listen(3000);
@@ -30,17 +35,47 @@ class CatsController {
3035
}
3136
```
3237

38+
#### Registering a different parser
39+
40+
By default, only `json` and `urlencoded` parsers are registered. If you want to register a different parser on the fly, you will need to do so explicitly.
41+
42+
For example, to register a `text` parser, you can use the following code:
43+
44+
```typescript
45+
app.useBodyParser('text');
46+
```
47+
48+
> warning **Warning** Ensure that you are providing the correct application type to the `NestFactory.create` call. For Express applications, the correct type is `NestExpressApplication`. Otherwise the `.useBodyParser` method will not be found.
49+
50+
#### Body parser size limit
51+
52+
If your application needs to parse a body larger than the default `100kb` of Express, use the following:
53+
54+
```typescript
55+
app.useBodyParser('json', { limit: '10mb' });
56+
```
57+
58+
The `.useBodyParser` method will respect the `rawBody` option that is passed in the application options.
59+
3360
#### Use with Fastify
3461

3562
First enable the option when creating your Nest Fastify application:
3663

3764
```typescript
65+
import { NestFactory } from '@nestjs/core';
66+
import {
67+
FastifyAdapter,
68+
NestFastifyApplication,
69+
} from '@nestjs/platform-fastify';
70+
import { AppModule } from './app.module';
71+
72+
// in the "bootstrap" function
3873
const app = await NestFactory.create<NestFastifyApplication>(
3974
AppModule,
4075
new FastifyAdapter(),
4176
{
4277
rawBody: true,
43-
}
78+
},
4479
);
4580
await app.listen(3000);
4681
```
@@ -59,3 +94,26 @@ class CatsController {
5994
}
6095
}
6196
```
97+
98+
#### Registering a different parser
99+
100+
By default, only `application/json` and `application/x-www-form-urlencoded` parsers are registered. If you want to register a different parser on the fly, you will need to do so explicitly.
101+
102+
For example, to register a `text/plain` parser, you can use the following code:
103+
104+
```typescript
105+
app.useBodyParser('text/plain');
106+
```
107+
108+
> warning **Warning** Ensure that you are providing the correct application type to the `NestFactory.create` call. For Fastify applications, the correct type is `NestFastifyApplication`. Otherwise the `.useBodyParser` method will not be found.
109+
110+
#### Body parser size limit
111+
112+
If your application needs to parse a body larger than the default 1MiB of Fastify, use the following:
113+
114+
```typescript
115+
const bodyLimit = 10_485_760; // 10MiB
116+
app.useBodyParser('application/json', { bodyLimit });
117+
```
118+
119+
The `.useBodyParser` method will respect the `rawBody` option that is passed in the application options.

content/faq/serverless.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ Also, depending on whether you want to run a typical HTTP application with multi
172172
your application's code will look different (for example, for the endpoint-per-function approach you could use the `NestFactory.createApplicationContext` instead of booting the HTTP server, setting up middleware, etc.).
173173

174174
Just for illustration purposes, we'll integrate Nest (using `@nestjs/platform-express` and so spinning up the whole, fully functional HTTP router)
175-
with the [Serverless](https://www.serverless.com/) framework (in this case, targetting AWS Lambda). As we've mentioned earlier, your code will differ depending on the cloud provider you choose, and many other factors.
175+
with the [Serverless](https://www.serverless.com/) framework (in this case, targeting AWS Lambda). As we've mentioned earlier, your code will differ depending on the cloud provider you choose, and many other factors.
176176

177177
First, let's install the required packages:
178178

0 commit comments

Comments
 (0)