Creating your first Node.js REST API with Nest and Typescript
Tags: javascript, webdev, node, beginners
Published: 2019-06-17 22:44:24

---
title: Creating your first Node.js REST API with Nest and Typescript
published: true
description: This is about how you can use Nest to create a REST API in Node.js. Nest brings a lot of needed structure to API creation
tags: javascript, webdev, node, beginners
---

Follow me on [Twitter](https://twitter.com/chris_noring), happy to take your suggestions on topics or improvements /Chris


> A progressive Node.js framework for building efficient, reliable and scalable server-side applications.

In this article, we will have a look at the Nest library. A library that makes authoring APIs a really nice experience. If you come from the Angular world you will surely recognize yourself with the concepts used, a great CLI and of course great usage of Typescript.

NOTE, it isn't Angular though but pretty darn close, in the best way possible.

This article is part of a series on Nest cause there is no way we could cover everything in one article.

We will cover the following:

- **Why Nest**, let's examine the *sales pitch* as well as mention the features that make Nest a really good choice for your next API
- **Your first CRUD project - covering the Fundamentals**, let's scaffold a project and go over the basic constructs

## Why Nest
Let's look at the sales pitch at the [homepage](https://nestjs.com)

- **Extensible**, allow the use of any other library thanks to modular architecture 
- **Versatile**, an adaptable ecosystem, for all kinds of server-side applications 
- **Progressive**, takes advantage of latest JavaScript features, design patterns, and mature solutions

> Ok, it all sounds great, but give me something I can WOW my colleagues with

It fully supports TypeScript, but use pure JavaScript if you prefer.

It uses the libraries `Express` and `Fastify` under the hood, but can also expose their APIs if needed.

> Sounds interesting, tell me more

It comes with a CLI, so you can scaffold a project as well as add artifacts.

> That's Nice

On top of that, you can easily write unit tests as well as E2E tests with Jest and you can easily build GraphQL APIs with it

> Stop it, you are making things up 

No really, check it out [Nest and GraphQL](https://docs.nestjs.com/graphql/quick-start) 

![](https://thepracticaldev.s3.amazonaws.com/i/aczn9zsdqztjvieoutim.gif)

## Resources

We will mention some great resources throughout this article. Should you miss out on the links we mention, here they are.

- [The official docs page](https://docs.nestjs.com/) 
The official docs page is a great page to start. It covers everything from fundamentals to Recipes
- [The overview section](https://docs.nestjs.com/first-steps) The whol overview section is a great read trying to understand the core concepts and you also get to use the CLI to scaffold a project
- [Recipes](https://docs.nestjs.com/recipes)
There are a lot of good recipes in there. Everything from how to work with different ORMs to setting up Swagger (which is super easy btw)

- [Deploy Nest to Serverless](https://github.com/nestjs/azure-func-http)
With a simple NPM install. 
  - Then have a look here to [Deploy Azure Function](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-vs-code?wt.mc_id=devto-blog-chnoring). 
  - You will need an Azure account, [Free account Azure account](https://azure.microsoft.com/en-gb/free/?wt.mc_id=devto-blog-chnoring)

## Your first project - covering the Fundamentals

Ok then. Let's do this. Before we start to create our first project, we need the CLI to create and run our project and many more things. We can easily install the CLI by using the following command:

```
npm i -g @nestjs/cli
```

Next up we need to scaffold a project. So let's do that next:

```
nest new hello-world
```

You can replace `hello-world` with a project name of your choice.

![](https://thepracticaldev.s3.amazonaws.com/i/6ct92xoanpppeyd9seai.png)

Ok, we got ourselves a lot of files. Judging by the above images we seemed to have gotten a Node.js project with `package.json` and some testing set up with Jest and of course a bunch of artifacts that seems Nest specific like *controller*, *module* and *service*. Let's have a close look at the scaffolded project:

### How does it work?

Before we run the project we just scaffolded, let's first have a closer look so we understand the lifecycle. First off let's look at `main.ts`. This is the entry point for our app. More specifically it's the `bootstrap()` method that starts up everything by running the code:

```ts
// main.ts

const app = await NestFactory.create(AppModule);
await app.listen(3000);
```

Ok, so `NestFactory` calls `create()` that instantiates the `AppModule` and we get an `app` instance that seems to listen on port `3000`. Let's go to `AppModule` and see what happens there:

```ts
//app.module.ts

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
```

Ok, we seem to have a class `AppModule` that is being decorated by `@Module` decorator that specific a controller `AppController` and something categorized as a provider `AppService`. 

> How does all of this work?

Well, the controller `AppController` responds to a route request so let's see how that one is set up:

```ts
// app.controller.ts

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}
```

The decorator `@Get()` ensures we map a certain GET request to a certain method on our class. In this case, the default route `/` will respond with the method `getHello()` which in turn invokes the `appService.getHello()`. Let's peek at `app.service.ts`:

```ts 
// app.service.ts

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}
```

This seems to be a very simple Class with a method `getHello()` that returns a string. 

Now, let's go back to `app.controller.ts`.

From what we can see `appService` is being injected in the constructor of `AppController` like so:

```ts
// excerpt from app.controller.ts

constructor(private readonly appService: AppService) {}
```

> How does it know how to do that?

There are two answers here:

1. If you add the `Injectable()` decorator to any service that means that it can be injected in other artifacts, like a controller or a service. 
2. This brings us to the second step. We need to add said service to the `providers` array for a module to make the DI machinery work.

> Oh? 

Yea let's try to cement this understanding a bit by going through the motions of adding a new route. But before we do that let's start this project and prove it works like we say it does:

```
npm start
```

![](https://thepracticaldev.s3.amazonaws.com/i/w1lfxplungmp2rqiuw7v.png)

Now, lets head to the browser:

![](https://thepracticaldev.s3.amazonaws.com/i/d40vrfdmytxguen0c0bb.png)

### Adding a route
We have just learned to scaffold a project and learned to run the same. We think we have a decent grasp on the concepts *module*, *controller* and *service* but nothing will cement this knowledge as much as adding a new route and add all the artifacts we need to make that possible. We will do the following:

We will create a new route `/products` and to do that, we need to carry out the following steps

1. Add a new service
2. Add a new controller and inject our service
3. Wire up the DI mechanism
4. Run our application and ensures everything works.

The first thing we are going to do is learn how to work with Nest projects properly. Right now we ran `npm start` which compiled our TypeScript code and hosted our app at port `3000` but during development, we might want something that listen to changes and compiles automatically. For that lets instead run the command `npm run start:dev`, which listens to changes and recompiles when needed.

```
npm run start:dev
```

![](https://thepracticaldev.s3.amazonaws.com/i/a9n97emvkxf7catkxg2t.png)

NOTE, before we start using the above command let's scaffold all the needed files and then we can run the above for when we are mucking about in specific code files and we want our changes to reflect. 

#### Creating a service
Let's create our products service. For now, make the data static, we can look at adding HTTP calls later. Let's do things the Nest way and use the CLI

```
nest generate service products
```

OR the shorter version

```
nest g s products
```

![](https://thepracticaldev.s3.amazonaws.com/i/9oi2yvomfqk9lbxabmgi.png)

Ok, open up the file `products/products.service.ts`. It should look like so:

```ts
import { Injectable } from '@nestjs/common';


@Injectable()
export class ProductsService {}
```

Now add the method `getProducts()` so it now looks like so:

```ts
import { Injectable } from '@nestjs/common';


@Injectable()
export class ProductsService {
  getProducts() {
    return [{
      id: 1,
      name: 'A SPA app'
    },
    {
      id: 2,
      name: 'A Nest API'
    }]
  }
}
```

#### Adding a controller
Time has come to create our controller, so let's do that next. Again we just the CLI, like so:

```
nest generate controller products
```

OR, shorter version

```
nest g co products
```

Open up `products/products.controller`:

```ts
import { Controller } from '@nestjs/common';

@Controller('products')
export class ProductsController {}
```

Next step is adding a method `getProducts()` and ensure we call our service and of course that we don't forget to decorate it with the `@Get()` decorator.

Your code should now look like this:

```ts
import { Controller, Get } from '@nestjs/common';
import { ProductsService } from './products.service';

@Controller('products')
export class ProductsController {
  constructor(private productsService: ProductsService) {}

  @Get()
  getProducts() {
    return this.productsService.getProducts();
  }
}
```

Let's try this out:

```
npm run start:dev
```

![](https://thepracticaldev.s3.amazonaws.com/i/1jmnsyacbw5lm8bibu3t.png)

Above we can see how our `/products` route seemed to have been added and that `ProductsController` will responds to any requests on that route. But how can this be, we haven't done anything to `app.module.ts` to wire up DI, or have we?

Let's look at `app.module.ts`:

![](https://thepracticaldev.s3.amazonaws.com/i/zmf8r8f0bpdmokwppylg.png)

We can see above that `ProductsController` and `ProductsService` have both been added to `controllers` and `providers` respectively. The CLI added it for us when we generated the controller and the service. 

We almost forgot something which was running our app in the browser, so let's do that:

![](https://thepracticaldev.s3.amazonaws.com/i/cfgbzz3crvqa0sx4ogua.png)

NOTE, the CLI is powerful it will not only create the necessary files but also do some wire up, but know what you need to do in case you don't use the CLI.

### Adding the remaining CRUD routes
Ok, so we've added a route to support `/products` route. As we all know though we need more routes than that like `POST`, `PUT`, `DELETE` and *wildcard* route, etc. 

> How do we add those?

Simple, we just have to create methods for each and everyone and add decorators to support it, like so:

```ts
// products.controller.ts

import { Controller, Get, Param, Post, Body, Put, Delete } from '@nestjs/common';
import { ProductsService } from './products.service';

interface ProductDto {
  id: string;
  name: string;
}

@Controller('products')
export class ProductsController {
  constructor(private productsService: ProductsService) {}

  @Get()
  getProducts() {
    return this.productsService.getProducts();
  }

  @Get(':id') 
  getProduct(@Param() params) {
    console.log('get a single product', params.id);
    return this.productsService.getProducts().filter(p => p.id == params.id);
  }

  @Post()
  createProduct(@Body() product: ProductDto) {
    console.log('create product', product);
    this.productsService.createProduct(product);
  }

  @Put()
  updateProduct(@Body() product: ProductDto) {
    console.log('update product', product);
    this.productsService.updateProduct(product);
  }

  @Delete()
  deleteProduct(@Body() product: ProductDto) {
    console.log('delete product', product.id);
    this.productsService.deleteProduct(product.id);
  }
}
```

and the `products.service.ts` now looks like this:

```ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class ProductsService {
  products = [{
    id: 1,
    name: 'A SPA app'
  },
  {
    id: 2,
    name: 'A Nest API'
  }];

  getProducts() {
    return this.products;
  }

  createProduct(product) {
    this.products = [...this.products, {...product}];
  }

  updateProduct(product) {
    this.products = this.products.map(p => {
      if (p.id == product.id) {
        return { ...product};
      }
      return p;
    });
  }

  deleteProduct(id) {
    this.products = this.products.filter(p => p.id != id);
  }
}

```

## Summary

Hopefully, you have realized by now how well-structured Nest is and how easy it is to create an API and read query parameters as well as body to support a full CRUD API. We've also introduced the CLI that truly is your best friend in generating the code you need and ensure you don't need to think about how to wire things up.

In our next part we will look at how test our code which is a truly blissful experience. So stay tuned for that.