Setup express with Typescript - controllers and routes
Tags: javascript, typescript, node
Published: 2022-07-12 07:01:57

### Introduction

In this series we will setup an express server using `Typescript`, we will be using `TypeOrm` as our ORM for querying a PostgresSql Database, we will also use `Jest` and `SuperTest` for testing. The goal of this series is not to create a full-fledged node backend but to setup an express starter project using typescript which can be used as a starting point if you want to develop a node backend using express and typescript.

### Overview

This series is not recommended for beginners some familiarity and experience working with `nodejs`, `express`, `typescript` and `typeorm` is expected. In this post which is part two of our series we will set up routing and controllers, we will cover the following : - 
 - Setup environment variables and `dotenv`.
 - Add todo controller.
 - Add todo routes.
 - Register the todo routes in our `express` app.

### Step One: Setup environment variables

In the last tutorial we hardcoded the server port in our `app.ts`, but as you all know we store all such information in environment variables. Similarly we store database credentials, logging levels all in environment variables. This comes handy when we deploy our applications to multiple environments like dev, staging, test, production we only need to tweak are the environment variables for each environment. In your terminal run 
```bash
npm install --save dotenv
```
Then under `app.ts` import the `dotenv` package, make sure this is the first import in our file : - 
```js
import "dotenv/config"
```
Now create 2 files namely `.env` & `.env.sample`, both in the root of our project not under `src`. **Make sure you add .env to the .gitignore file** which we did in the previous tutorial. `.env` and `.env.sample` will have the same keys only difference is that `.env` has values and `.env.sample` will only have keys. This makes it handy so that we can commit `.env.sample` to git.

Under `.env` file paste the following : -
```
NODE_ENV=development
SERVER_PORT=8080
```

Under `.env.sample` paste the following : - 
```
NODE_ENV=
SERVER_PORT=
```

Now in `app.ts` file for the port variable we do : - 
```ts
private readonly port = process.env.SERVER_PORT || 8080
```

### Step Two: Add Todo Controller

Lets create a new folder under `src` called `api` and under `api` folder create another folder called `todos`. Inside the `todos` folder create a new file called `todos.controller.ts` and paste the following code : - 
```ts
import { Request, Response } from 'express'

const todos = [
   {
     id: '1',
     text: 'Run daily for 15 minutes',
   },
   {
     id: '2',
     text: 'Buy coffe',
   },
]

class TodoController {
  getAllTodos(req: Request, res: Response) {
   return res.status(200).json({
      status: true,
      statusCode: 200,
      todos,
    })
  }

  getTodoById(req: Request, res: Response) { 
    const { id } = req.params
    const todo = todos.find((todo) => todo.id === id)
    if (!todo) {
	 return res.status(404).json({
	   status: false,
	   statusCode: 404,
	   message: `todo not found for id - ${id}`,
	 })
    }
    
     return res.status(200).json({
       status: true,
       statusCode: 200,
       todo,
     })
  }	
}

export const todosController = new TodoController()
```
The above code is very basic 2 controllers one for `getAll` and other for `getById`. Given that we have'nt setup our database connection yet we have a dummy todos list. At the end of our file we created an object of our controller class and exported it, you don't need to use classes, normal javascript functions will do.

### Step Three: Add todo routes

Now let us setup a base router, under the `src` folder create a new folder called `utils` and under `utils` create a new file called `BaseRouter.ts` in this file paste the following code : - 
```ts
import { Router } from 'express'

interface IRouter {
  router: Router;
  addRoutes(): void;
  returnApiEndpointRouter(): Router
}

export abstract class BaseRouter implements IRouter {
  router: Router

  constructor() {
     this.router = Router()
  }

  abstract addRoutes(): void

  abstract returnApiEndpointRouter(): Router;
}
```
We created an abstract class, all our Route classes will extend this abstract class and when they do so they have to implement all the abstract methods like `routes and returnApiEndpointRouter`. Remember for abstract methods we only declare the methods using the `abstract` keyword we implement these methods in the child classes; those classes that will extend the `BaseRouter` abstract class.

Now under `src/api/todos` create a new file `todos.router.ts` and paste the following code : - 
```ts
import { Router } from 'express'
import { BaseRouter } from '../../utils/BaseRouter'
import { todosController } from './todos.controller'

class TodosRouter extends BaseRouter {
 constructor() {
   super()
  }

  addRoutes(): void {
    this.router.get('/', todosController.getAllTodos)
    this.router.get('/:id', todosController.getTodoById)
  }

   returnApiEndpointRouter(): Router {
     this.addRoutes()
     return this.router
   }
}

export const todosRouter = new TodosRouter().returnApiEndpointRouter()
```
We extended the `BaseRouter` abstract class implemented all the abstract methods, registered our routes in the `addRoutes()` method and finally created our router. The `this.router` is inherited from the parent `BaseRouter` abstract class.

### Step Four: Register the todo router in our express app

Now in the `server.ts` file under the `addRoutes()` method paste the following code : - 
```ts
private addRoutes() {
  this.app.use('/api/todos', todosRouter)
}
```  
And done we have added our route. Now from your terminal run `npm run dev` and check our todo routes by visiting - 
- `http://localhost:8080/api/todos` - get all todos. 
- `http://localhost:8080/api/todos/2` - get the second todo.

### Summary
There you go our basic routing and controller setup is completed.  I hope you like the modularity and structure for our project. All the code for this tutorial can be found under the `feat/setup-todo-routes` branch [here](https://github.com/yaldram/express-typescript-starter/tree/feat/setup-todo-routes). In the next tutorial we will connect to a database until next time PEACE.