From 56fd4a26412570ec68e449bc531baa236518f5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Thu, 17 Oct 2024 10:10:09 +0200 Subject: [PATCH] docs: update listen to use port env variable --- .prettierrc | 3 ++- content/devtools/ci-cd.md | 6 ++--- content/devtools/overview.md | 4 ++-- content/exception-filters.md | 11 ++++++---- content/faq/keep-alive-connections.md | 2 +- content/faq/multiple-servers.md | 28 +++++++++++------------- content/faq/raw-body.md | 4 ++-- content/faq/serverless.md | 2 +- content/first-steps.md | 4 ++-- content/fundamentals/lifecycle-events.md | 2 +- content/middlewares.md | 10 +++++---- content/openapi/introduction.md | 7 +++--- content/openapi/other-features.md | 2 +- content/pipes.md | 2 +- content/recipes/hot-reload.md | 9 +++----- content/security/cors.md | 4 ++-- content/techniques/logger.md | 12 +++++----- content/techniques/mvc.md | 8 +++---- content/techniques/performance.md | 4 +--- content/techniques/validation.md | 6 ++--- content/techniques/versioning.md | 8 +++---- 21 files changed, 68 insertions(+), 70 deletions(-) diff --git a/.prettierrc b/.prettierrc index a20502b7..94099675 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { "singleQuote": true, - "trailingComma": "all" + "trailingComma": "all", + "printWidth": 80 } diff --git a/content/devtools/ci-cd.md b/content/devtools/ci-cd.md index b91d3624..a88b5f63 100644 --- a/content/devtools/ci-cd.md +++ b/content/devtools/ci-cd.md @@ -40,7 +40,7 @@ async function bootstrap() { await app.close(); } else { - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } } ``` @@ -232,9 +232,7 @@ const publishOptions = { sha: process.env.CI_COMMIT_SHA, target: process.env.CI_MERGE_REQUEST_DIFF_BASE_SHA, trigger: process.env.CI_MERGE_REQUEST_DIFF_BASE_SHA ? 'pull' : 'push', - branch: - process.env.CI_COMMIT_BRANCH ?? - process.env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME, + branch: process.env.CI_COMMIT_BRANCH ?? process.env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME, }; ``` diff --git a/content/devtools/overview.md b/content/devtools/overview.md index 674f625c..5aebdd10 100644 --- a/content/devtools/overview.md +++ b/content/devtools/overview.md @@ -9,7 +9,7 @@ async function bootstrap() { const app = await NestFactory.create(AppModule, { snapshot: true, }); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } ``` @@ -185,7 +185,7 @@ This page comes in handy when you want to identify potential issues in your appl To save a serialized graph to a file, use the following code: ```typescript -await app.listen(3000); // OR await app.init() +await app.listen(process.env.PORT ?? 3000); // OR await app.init() fs.writeFileSync('./graph.json', app.get(SerializedGraph).toString()); ``` diff --git a/content/exception-filters.md b/content/exception-filters.md index 28c3b9f7..0af0a2bf 100644 --- a/content/exception-filters.md +++ b/content/exception-filters.md @@ -141,7 +141,10 @@ Nest provides a set of standard exceptions that inherit from the base `HttpExcep All the built-in exceptions can also provide both an error `cause` and an error description using the `options` parameter: ```typescript -throw new BadRequestException('Something bad happened', { cause: new Error(), description: 'Some error description' }) +throw new BadRequestException('Something bad happened', { + cause: new Error(), + description: 'Some error description', +}); ``` Using the above, this is how the response would look: @@ -150,7 +153,7 @@ Using the above, this is how the response would look: { "message": "Something bad happened", "error": "Some error description", - "statusCode": 400, + "statusCode": 400 } ``` @@ -278,7 +281,7 @@ To create a global-scoped filter, you would do the following: async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalFilters(new HttpExceptionFilter()); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` @@ -394,7 +397,7 @@ async function bootstrap() { const { httpAdapter } = app.get(HttpAdapterHost); app.useGlobalFilters(new AllExceptionsFilter(httpAdapter)); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` diff --git a/content/faq/keep-alive-connections.md b/content/faq/keep-alive-connections.md index 245e8e16..a2e82d50 100644 --- a/content/faq/keep-alive-connections.md +++ b/content/faq/keep-alive-connections.md @@ -18,7 +18,7 @@ async function bootstrap() { const app = await NestFactory.create(AppModule, { forceCloseConnections: true, }); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); diff --git a/content/faq/multiple-servers.md b/content/faq/multiple-servers.md index 66a9d6e8..8c4a84c3 100644 --- a/content/faq/multiple-servers.md +++ b/content/faq/multiple-servers.md @@ -10,7 +10,7 @@ const httpsOptions = { const app = await NestFactory.create(AppModule, { httpsOptions, }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` If you use the `FastifyAdapter`, create the application as follows: @@ -33,10 +33,7 @@ const httpsOptions = { }; const server = express(); -const app = await NestFactory.create( - AppModule, - new ExpressAdapter(server), -); +const app = await NestFactory.create(AppModule, new ExpressAdapter(server)); await app.init(); const httpServer = http.createServer(server).listen(3000); @@ -56,16 +53,17 @@ export class ShutdownObserver implements OnApplicationShutdown { public async onApplicationShutdown(): Promise { await Promise.all( - this.httpServers.map((server) => - new Promise((resolve, reject) => { - server.close((error) => { - if (error) { - reject(error); - } else { - resolve(null); - } - }); - }) + this.httpServers.map( + (server) => + new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error); + } else { + resolve(null); + } + }); + }), ), ); } diff --git a/content/faq/raw-body.md b/content/faq/raw-body.md index 6922f20a..43c07112 100644 --- a/content/faq/raw-body.md +++ b/content/faq/raw-body.md @@ -17,7 +17,7 @@ import { AppModule } from './app.module'; const app = await NestFactory.create(AppModule, { rawBody: true, }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` To access the raw request body in a controller, a convenience interface `RawBodyRequest` is provided to expose a `rawBody` field on the request: use the interface `RawBodyRequest` type: @@ -77,7 +77,7 @@ const app = await NestFactory.create( rawBody: true, }, ); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` To access the raw request body in a controller, a convenience interface `RawBodyRequest` is provided to expose a `rawBody` field on the request: use the interface `RawBodyRequest` type: diff --git a/content/faq/serverless.md b/content/faq/serverless.md index 87ec8908..9241c86a 100644 --- a/content/faq/serverless.md +++ b/content/faq/serverless.md @@ -37,7 +37,7 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule, { logger: ['error'] }); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); diff --git a/content/first-steps.md b/content/first-steps.md index 23e7012f..4b3d9357 100644 --- a/content/first-steps.md +++ b/content/first-steps.md @@ -56,7 +56,7 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); @@switch @@ -65,7 +65,7 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` diff --git a/content/fundamentals/lifecycle-events.md b/content/fundamentals/lifecycle-events.md index e5a79280..6e687bd1 100644 --- a/content/fundamentals/lifecycle-events.md +++ b/content/fundamentals/lifecycle-events.md @@ -84,7 +84,7 @@ async function bootstrap() { // Starts listening for shutdown hooks app.enableShutdownHooks(); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` diff --git a/content/middlewares.md b/content/middlewares.md index 4a9ceaf1..05bfe04d 100644 --- a/content/middlewares.md +++ b/content/middlewares.md @@ -20,8 +20,7 @@ Nest middleware are, by default, equivalent to [express](https://expressjs.com/e You implement custom Nest middleware in either a function, or in a class with an `@Injectable()` decorator. The class should implement the `NestMiddleware` interface, while the function does not have any special requirements. Let's start by implementing a simple middleware feature using the class method. -> warning **Warning** `Express` and `fastify` handle middleware differently and provide different method signatures, read more [here](/techniques/performance#middleware). - +> warning **Warning** `Express` and `fastify` handle middleware differently and provide different method signatures, read more [here](/techniques/performance#middleware). ```typescript @@filename(logger.middleware) @@ -132,7 +131,10 @@ export class AppModule { Pattern based routes are supported as well. For instance, the asterisk is used as a **wildcard**, and will match any combination of characters: ```typescript -forRoutes({ path: 'ab*cd', method: RequestMethod.ALL }); +forRoutes({ + path: 'ab*cd', + method: RequestMethod.ALL, +}); ``` The `'ab*cd'` route path will match `abcd`, `ab_cd`, `abecd`, and so on. The characters `?`, `+`, `*`, and `()` may be used in a route path, and are subsets of their regular expression counterparts. The hyphen ( `-`) and the dot (`.`) are interpreted literally by string-based paths. @@ -245,7 +247,7 @@ If we want to bind middleware to every registered route at once, we can use the @@filename(main) const app = await NestFactory.create(AppModule); app.use(logger); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` > info **Hint** Accessing the DI container in a global middleware is not possible. You can use a [functional middleware](middleware#functional-middleware) instead when using `app.use()`. Alternatively, you can use a class middleware and consume it with `.forRoutes('*')` within the `AppModule` (or any other module). diff --git a/content/openapi/introduction.md b/content/openapi/introduction.md index 9eb6ecba..70443e87 100644 --- a/content/openapi/introduction.md +++ b/content/openapi/introduction.md @@ -32,7 +32,7 @@ async function bootstrap() { const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` @@ -62,14 +62,15 @@ As you can see, the `SwaggerModule` automatically reflects all of your endpoints > info **Hint** To generate and download a Swagger JSON file, navigate to `http://localhost:3000/api-json` (assuming that your Swagger documentation is available under `http://localhost:3000/api`). > It is also possible to expose it on a route of your choice using only the setup method from `@nestjs/swagger`, like this: +> > ```typescript > SwaggerModule.setup('swagger', app, document, { > jsonDocumentUrl: 'swagger/json', > }); > ``` +> > Which would expose it at `http://localhost:3000/swagger/json` - > warning **Warning** When using `fastify` and `helmet`, there may be a problem with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), to solve this collision, configure the CSP as shown below: > > ```typescript @@ -187,7 +188,7 @@ export interface SwaggerCustomOptions { /** * If `true`, the selector of OpenAPI definitions is displayed in the Swagger UI interface. * Default: `false`. - * + * * When `true` and `swaggerOptions.urls` is provided, a dropdown labeled "Select a definition" * is shown in the Swagger UI, allowing users to select from the available API definitions * specified in the `urls` array. diff --git a/content/openapi/other-features.md b/content/openapi/other-features.md index e3bd41df..3e20ddf1 100644 --- a/content/openapi/other-features.md +++ b/content/openapi/other-features.md @@ -75,7 +75,7 @@ async function bootstrap() { }); SwaggerModule.setup('api/dogs', app, dogDocument); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` diff --git a/content/pipes.md b/content/pipes.md index 66f53942..fa5e98d5 100644 --- a/content/pipes.md +++ b/content/pipes.md @@ -430,7 +430,7 @@ Since the `ValidationPipe` was created to be as generic as possible, we can real async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe()); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` diff --git a/content/recipes/hot-reload.md b/content/recipes/hot-reload.md index 3222c58a..ce1f3578 100644 --- a/content/recipes/hot-reload.md +++ b/content/recipes/hot-reload.md @@ -60,7 +60,7 @@ declare const module: any; async function bootstrap() { const app = await NestFactory.create(AppModule); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); if (module.hot) { module.hot.accept(); @@ -127,10 +127,7 @@ module.exports = { resolve: { extensions: ['.tsx', '.ts', '.js'], }, - plugins: [ - new webpack.HotModuleReplacementPlugin(), - new RunScriptWebpackPlugin({ name: 'server.js', autoRestart: false }), - ], + plugins: [new webpack.HotModuleReplacementPlugin(), new RunScriptWebpackPlugin({ name: 'server.js', autoRestart: false })], output: { path: path.join(__dirname, 'dist'), filename: 'server.js', @@ -151,7 +148,7 @@ declare const module: any; async function bootstrap() { const app = await NestFactory.create(AppModule); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); if (module.hot) { module.hot.accept(); diff --git a/content/security/cors.md b/content/security/cors.md index 95b50eec..fb5d68aa 100644 --- a/content/security/cors.md +++ b/content/security/cors.md @@ -9,7 +9,7 @@ To enable CORS, call the `enableCors()` method on the Nest application object. ```typescript const app = await NestFactory.create(AppModule); app.enableCors(); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` The `enableCors()` method takes an optional configuration object argument. The available properties of this object are described in the official [CORS](https://github.com/expressjs/cors#configuration-options) documentation. Another way is to pass a [callback function](https://github.com/expressjs/cors#configuring-cors-asynchronously) that lets you define the configuration object asynchronously based on the request (on the fly). @@ -19,5 +19,5 @@ Or, pass a [CORS configuration object](https://github.com/expressjs/cors#configu ```typescript const app = await NestFactory.create(AppModule, { cors: true }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` diff --git a/content/techniques/logger.md b/content/techniques/logger.md index 9a5e4d58..a871455d 100644 --- a/content/techniques/logger.md +++ b/content/techniques/logger.md @@ -21,7 +21,7 @@ To disable logging, set the `logger` property to `false` in the (optional) Nest const app = await NestFactory.create(AppModule, { logger: false, }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` To enable specific logging levels, set the `logger` property to an array of strings specifying the log levels to display, as follows: @@ -30,7 +30,7 @@ To enable specific logging levels, set the `logger` property to an array of stri const app = await NestFactory.create(AppModule, { logger: ['error', 'warn'], }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` Values in the array can be any combination of `'log'`, `'fatal'`, `'error'`, `'warn'`, `'debug'`, and `'verbose'`. @@ -45,7 +45,7 @@ You can provide a custom logger implementation to be used by Nest for system log const app = await NestFactory.create(AppModule, { logger: console, }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` Implementing your own custom logger is straightforward. Simply implement each of the methods of the `LoggerService` interface as shown below. @@ -93,7 +93,7 @@ You can then supply an instance of `MyLogger` via the `logger` property of the N const app = await NestFactory.create(AppModule, { logger: new MyLogger(), }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` This technique, while simple, doesn't utilize dependency injection for the `MyLogger` class. This can pose some challenges, particularly for testing, and limit the reusability of `MyLogger`. For a better solution, see the Dependency Injection section below. @@ -148,7 +148,7 @@ const app = await NestFactory.create(AppModule, { bufferLogs: true, }); app.useLogger(app.get(MyLogger)); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` > info **Note** In the example above, we set the `bufferLogs` to `true` to make sure all logs will be buffered until a custom logger is attached (`MyLogger` in this case) and the application initialisation process either completes or fails. If the initialisation process fails, Nest will fallback to the original `ConsoleLogger` to print out any reported error messages. Also, you can set the `autoFlushLogs` to `false` (default `true`) to manually flush logs (using the `Logger#flush()` method). @@ -249,7 +249,7 @@ const app = await NestFactory.create(AppModule, { bufferLogs: true, }); app.useLogger(new MyLogger()); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` > info **Hint** Alternatively, instead of setting `bufferLogs` to `true`, you could temporarily disable the logger with `logger: false` instruction. Be mindful that if you supply `logger: false` to `NestFactory.create`, nothing will be logged until you call `useLogger`, so you may miss some important initialization errors. If you don't mind that some of your initial messages will be logged with the default logger, you can just omit the `logger: false` option. diff --git a/content/techniques/mvc.md b/content/techniques/mvc.md index 667fa344..add35e4f 100644 --- a/content/techniques/mvc.md +++ b/content/techniques/mvc.md @@ -33,7 +33,7 @@ async function bootstrap() { app.setBaseViewsDir(join(__dirname, '..', 'views')); app.setViewEngine('hbs'); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); @@switch @@ -50,7 +50,7 @@ async function bootstrap() { app.setBaseViewsDir(join(__dirname, '..', 'views')); app.setViewEngine('hbs'); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` @@ -156,7 +156,7 @@ async function bootstrap() { }, templates: join(__dirname, '..', 'views'), }); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); @@switch @@ -177,7 +177,7 @@ async function bootstrap() { }, templates: join(__dirname, '..', 'views'), }); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` diff --git a/content/techniques/performance.md b/content/techniques/performance.md index 0386c9ef..1fd4ce78 100644 --- a/content/techniques/performance.md +++ b/content/techniques/performance.md @@ -34,7 +34,7 @@ async function bootstrap() { AppModule, new FastifyAdapter() ); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` @@ -74,7 +74,6 @@ You can pass options into the Fastify constructor through the `FastifyAdapter` c new FastifyAdapter({ logger: true }); ``` - #### Middleware Middleware functions retrieve the raw `req` and `res` objects instead of Fastify's wrappers. This is how the `middie` package works (that's used under the hood) and `fastify` - check out this [page](https://www.fastify.io/docs/latest/Reference/Middleware/) for more information, @@ -128,7 +127,6 @@ newFeature() { > info **Hint** `@RouteConfig()` and `@RouteConstraints` are imported from `@nestjs/platform-fastify`. - #### Example A working example is available [here](https://github.com/nestjs/nest/tree/master/sample/10-fastify). diff --git a/content/techniques/validation.md b/content/techniques/validation.md index b7fcff36..286ef959 100644 --- a/content/techniques/validation.md +++ b/content/techniques/validation.md @@ -141,7 +141,7 @@ We'll start by binding `ValidationPipe` at the application level, thus ensuring async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe()); - await app.listen(3000); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); ``` @@ -155,7 +155,7 @@ create(@Body() createUserDto: CreateUserDto) { } ``` -> info **Hint** Since TypeScript does not store metadata about **generics or interfaces**, when you use them in your DTOs, `ValidationPipe` may not be able to properly validate incoming data. For this reason, consider using concrete classes in your DTOs. +> info **Hint** Since TypeScript does not store metadata about **generics or interfaces**, when you use them in your DTOs, `ValidationPipe` may not be able to properly validate incoming data. For this reason, consider using concrete classes in your DTOs. > info **Hint** When importing your DTOs, you can't use a type-only import as that would be erased at runtime, i.e. remember to `import {{ '{' }} CreateUserDto {{ '}' }}` instead of `import type {{ '{' }} CreateUserDto {{ '}' }}`. @@ -237,7 +237,7 @@ Alternatively, you can stop the request from processing when non-whitelisted pro #### Transform payload objects -Payloads coming in over the network are plain JavaScript objects. The `ValidationPipe` can automatically transform payloads to be objects typed according to their DTO classes. To enable auto-transformation, set `transform` to `true`. This can be done at a method level: +Payloads coming in over the network are plain JavaScript objects. The `ValidationPipe` can automatically transform payloads to be objects typed according to their DTO classes. To enable auto-transformation, set `transform` to `true`. This can be done at a method level: ```typescript @@filename(cats.controller) diff --git a/content/techniques/versioning.md b/content/techniques/versioning.md index b80d0b10..98a0a2c8 100644 --- a/content/techniques/versioning.md +++ b/content/techniques/versioning.md @@ -40,7 +40,7 @@ const app = await NestFactory.create(AppModule); app.enableVersioning({ type: VersioningType.URI, }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` > warning **Notice** The version in the URI will be automatically prefixed with `v` by default, however the prefix value can be configured by setting the `prefix` key to your desired prefix or `false` if you wish to disable it. @@ -62,7 +62,7 @@ app.enableVersioning({ type: VersioningType.HEADER, header: 'Custom-Header', }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` The `header` property should be the name of the header that will contain the version of the request. @@ -84,7 +84,7 @@ app.enableVersioning({ type: VersioningType.MEDIA_TYPE, key: 'v=', }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` The `key` property should be the key and separator of the key-value pair that contains the version. For the example `Accept: application/json;v=2`, the `key` property would be set to `v=`. @@ -130,7 +130,7 @@ app.enableVersioning({ type: VersioningType.CUSTOM, extractor, }); -await app.listen(3000); +await app.listen(process.env.PORT ?? 3000); ``` #### Usage