Self-paced

Explore our extensive collection of courses designed to help you master various subjects and skills. Whether you're a beginner or an advanced learner, there's something here for everyone.

Bootcamp

Learn live

Join us for our free workshops, webinars, and other events to learn more about our programs and get started on your journey to becoming a developer.

Upcoming live events

Learning library

For all the self-taught geeks out there, here is our content library with most of the learning materials we have produced throughout the years.

It makes sense to start learning by reading and watching videos about fundamentals and how things work.

Search from all Lessons


LoginGet Started
← Back to Lessons
Edit on Github

Start your API with Express.js and Typescript.js

Quick Start

🍬 Technologies: TypeORM, TypeScript, Node.js, Express.js, Postgres

Quick Start

Creating an API is basically creating a list of endpoints that you want other developers to request whenever they need to interact with your database to Create, Update, Delete or Read information. When using Express.js those endpoints have to be added into your API using the router.get (or post, put or delete) function. For example:

1router.get("/users", getUser)

The line above, specifies a new endpoint that other devs will be able to call by requesting GET /users.

After declaring your route, you also have to declare your function that will handle that request (in this case getUser)

The two main files you care about are ./src/<private|public>_routes.ts and ./src/actions.ts and you will have to always modify both every time you create a new endpoint.

1) Adding the route URL

Public or Private endpoint?

First you have to think about your endpoint security, who will be using this endpoint? Any public user or only the logged in users?

There are two files and you should update one or the other for each endpoint you create:

  • public_routes.ts is for API URLs that are going to be used by anyone, no security whatsoever, for example: Everyone can sign up, everyone can try to login, etc.
  • private_routes.ts these URLs will be only for logged in users, for example: Get my list of favorites, or get my information, etc.

Open your chosen ./src/<private|public>_routes.ts file and add a new route to the list of endpoints, for example, if we want to build an endpoint to retrieve a single user information by a given ID, for example: GET /user/2

1import { Router } from 'express'; 2import { safe } from './utils'; 3import { getUser } from './actions'; 4const router = Router(); 5 6 7router.get('/user/:id', safe(getUser));

πŸ‘‰ Note: please note that the safe function must always be called before your action or the API errors will be silent.

2) Declaring your actions.ts

Open the ./src/actions.ts and add or re-use one of the action functions, for example:

1export const getUser = async (req: Request, res: Response): Promise<Response> =>{ 2 3 const users = await getRepository(Users).findOne(req.params.id); 4 return res.json(users); 5}

Validate incoming requests

Junior developers always assume that everything will be O.K. while Senior developers are prepared for the worst possible scenarios.

You have to assume that the information is coming in a bad format, for example: Emails don't have the domain name inside, phone numbers have letters, etc.

There are three possible types of validations that we recommend doing:

A) Validating the request payload (body)

The request payload can be retrieved by doing req.body, this is an example on how to validate if the request body contains the property first_name:

1export const getUser = async (req: Request, res:Response): Promise<Response> =>{ 2 3 // validate that first_name exists or throw a new exception if not. 4 if(!req.body.first_name) throw new Exception("Please provide a first_name") 5 6 // the rest of your function code goes here 7 8})

B) Validating the request params (in the url)

If your endpoint URL is expecting a parameter you can access it by typing req.params, for example, if the endpoint GET /user/:id is called with GET /user/23, we can retrieve the value like this:

1 const user = await getRepository(Users).findOne(req.params.id); 2 if(!user) throw new Exception("User not found", 404)

We are basically querying the database to get the user with that given ID and make sure it exists.

C) Other validation examples

In the following file πŸ”₯πŸ”₯πŸ”₯ you can find more validation examples.

Database Query (Get information)

TypeORM has a lot of ways to retrieve information from the database, we are going to show the most used examples here, and you can check this document for more advanced ways to query information.

⚠️ Important: You must always start by declaring a new repository for that entity

1const user = repository.create({ 2 id: 1, 3 firstName: "Timber", 4 lastName: "Saw", 5}) // same as const user = new User(); user.firstName = "Timber"; user.lastName = "Saw";

After having the repository object you can start your query, for example:

Find by

Find the user with the first name "Bob"

1userRepository.find({ where: { firstName: "Bob", lastName: "Saw" } });

Find by (many)

Find the user with the first name "Bob"

1userRepository.find({ where: { firstName: "Bob", lastName: "Saw" } });

Find One by (just one)

Find the user with the first name "Bob"

1userRepository.findOne(1, { 2 where: { firstName: "Bob" } 3})

More advanced queries

πŸ”₯πŸ”₯πŸ”₯ Click here for more advanced query examples

Database CRUD operations

TypeORM is one of the most simple-to-use ORM library.

Create a user

Here is a very simple example on how to create a new user:

1const user = repository.create({ 2 id: 1, 3 firstName: "Timber", 4 lastName: "Saw" 5}); // same as const user = new User(); user.firstName = "Timber"; user.lastName = "Saw";

Delete a user

Assuming you want to delete user with ID=1

1await repository.delete(1);

Update a user

Assuming you want to update the user with the ID=1 and set his/her name to Rizzrak:

1await repository.update(1, { firstName: "Rizzrak" });

πŸ”₯πŸ”₯πŸ”₯ Here you can find other example of more complex CRUD operations.

Migrations (only for production environment)

You don't have to use migrations in development mode because TypeORM already does that for you, but before moving to production you have to run the following command to create your migrations:

  1. Generate a new migration file after changes were made to the models:
1$ npm run makemigrations
  1. Apply all of your pending migrations:
1$ npm run migrate

PostgreSQL

This will give you an auto-starting PostgreSQL server (it should auto-start every time you open a new Terminal), plus a few utility scripts that you can run in a Terminal or in a .gitpod.yml command:

pg_start: start the PostgreSQL service
pg_stop: stop the PostgreSQL service
pg_ctl status: check if the PostgreSQL service is running
Once the PostgreSQL server is running, you can use the psql CLI as usual:

$ psql -h localhost -d postgres
psql (10.8 (Ubuntu 10.8-0ubuntu0.18.10.1))
Type "help" for help.

postgres=#

How to implement a JWT schema on my API with Express?

In this article you will find the details about how to implement this schema on your Express API