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
npm install --save dotenv
Then under app.ts
import the dotenv
package, make sure this is the first import in our file : -
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 : -
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 : -
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 : -
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 : -
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 : -
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. In the next tutorial we will connect to a database until next time PEACE.
Top comments (0)