A simple guide to setting up a project with Node.js, Typescript, Postgres and TypeORM

Icegreen
7 min readAug 14, 2023

--

The purpose of this article is to teach you how to start your project from scratch with Node.js, express, typescript, postgres and typeORM.

Steps:

-Configure the project
- Initialize the server and the database | MySQL or Postgres
- Environment variables
- Command scripts
- Creating the entities with TypeORM
- Configuring and running migration
-

1 — Configure the project

Create your project:

yarn init -y

Install the following technologies as a development dependency:

npm install @types/express @types/node nodemon ts-node typescript dotenv express pg reflect-metadata typeorm

Dotenv: Library for loading environment variables from an .env file into your application settings.

Express: Web framework for Node.js

Pg: Library for interacting with PostgreSQL databases from Node.js applications.

Reflect-metadata: Library that provides reflection metadata for TypeScript classes, properties, and methods.

Typeorm: It simplifies communication between your application and relational databases by abstracting query logic.

Run the npx typescript — init command to create a tsconfig.json file, this is a configuration file used in TypeScript projects. It controls the compilation options and behavior of the TypeScript compiler (tsc) when you transform TypeScript code into JavaScript code, which is what the browser or Node.js can execute.

Inside the file you will have a huge list of instructions, delete everything because we won’t need all of them, just these:

{
"compilerOptions": {
"target": "es2018",
"lib": ["es5", "es6", "ES2018"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "commonjs",
"moduleResolution": "node",
"resolveJsonModule": true,
"allowJs": true,
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitAny": true,
"strictPropertyInitialization": false
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"],
"ts-node": {
"files": true
}
}

2 — Initialize the server and the database | MySQL or Postgres

With the project started, let’s configure the settings. Open a `src` folder, create a `data-source.ts` file and write the following content:

import 'dotenv/config';
import 'reflect-metadata';
import { DataSource } from "typeorm";

const port = process.env.DB_PORT as number | undefined;

export const AppDataSource = new DataSource({
type: 'postgres',
host: process.env.DB_HOST,
port: port,
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,

entities: [`${__dirname}/**/entities/*.{ts,js}`],
migrations: [`${__dirname}/**/migrations/*.{ts,js}`]
})

This code sets up a connection to a PostgreSQL database using TypeORM:

It imports the variables from the .env file (used to keep secret information). Configures a data source (DataSource) for the TypeORM. Uses environment information (such as host, port, username and password) to connect to the database. Indicates where to find the models (entities) and migrations. All of this helps keep database configurations secure and flexible.

The `data-source.ts` file is generally used in application development contexts that deal with databases, especially when using an architectural pattern such as ORM (Object-Relational Mapping).

After that, let’s start the server. Create an `index.ts` file in the src folder and place the following content:

import express from 'express';
import { AppDataSource } from './data-source';

AppDataSource.initialize().then(() => {
const app = express();
app.use(express.json())
app.get('/', (req, res) => {
return res.json('Established connection!');
})
return app.listen(process.env.PORT);
})

This code creates a web server using Express, initiates a connection to the database, and defines a route that responds with ‘Established connection’ when you access the root of the server.

Another more important detail, the `AppDataSource.initialize() `approach allows the server to only be started from the moment it connects to the database. Preventing the server from starting without being connected to the database.

3 — Environment variables

Create an .env file in the root of the project and place the following environment variables:

DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASS=postgres
DB_NAME=postgres

PORT=3000

*Make sure the port, user, name, password and your database name match.

Let’s start the application, first, make sure that the postgress database is running on your machine, if you don’t know, follow the tutorial: Installing and Using PostgreSQL Locally

In your packge.json create a script and put the following content:

"scripts": {
"dev": "nodemon --exec ts-node ./src/index.ts",
},

This snippet in a package.json file defines a script named “dev”. When you run yarn dev, it uses nodemon and ts-node to monitor a TypeScript file (./src/index.ts) and automatically restart the server every time you make changes.

Now to start the server, make sure that the postgres database is running on your machine with the proper references in the .env set.

Linux terminal:

PostgresSQL running on the machine

Beekeeper: database manager

Creating the database connection with Beekeeper

After running your database, in your application’s terminal, type yarn dev and your application will start:

Now that the server is running, let’s verify the database connection through POSTMAN. Doing a query on the server url, we will have the following return:

With this return it means that the connection to the database was made and that the server is running.

4 — Creating entities with TypeORM

What are entities?

They are classes or objects that are mapped to tables in a relational database. To achieve this, we use ORM (Object-Relational Mapping), which is a technique in software development that enables us to perform mapping between objects and classes in the programming language and tables in the database. This makes it easier for developers to manipulate data without having to deal directly with SQL.

Knowing this, create a folder called entities and create a file called Room.ts and Videos.ts.

In Room.ts paste the following code:

import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { Video } from "./Video";

@Entity('rooms')
export class Room {
@PrimaryGeneratedColumn()
id: number

@Column({type: 'text'})
name: string;

@Column({ type: 'text', nullable: true})
description: string

@OneToMany(() => Video, (video) => video.room)
videos: Video[];
}

This code defines a class called Room using the TypeORM. Each instance of the class represents a row in the database table called “rooms”. The table has id, name and description columns, where the id is automatically generated. Also, there is a “one-to-many” relationship with the Video class, which means that a room can have multiple videos associated with it.

In Video.ts paste the following code:

import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
import { Room } from './Room';

@Entity('videos')
export class Video {
@PrimaryGeneratedColumn()
id: number

@Column({ type: 'text' })
title: string

@Column({ type: 'text' })
url: string

@ManyToOne(() => Room, room => room.videos)
@JoinColumn({ name: 'room_id'}) // foreign key
room: Room
}

In short, this code defines the Video class as an entity that represents a table in the database called “videos”. The table has columns for id, title and url. In addition, there is a “many-to-one” relationship with the Room class, indicating the room the video belongs to, via the room_id foreign key column. This lets you model the relationship between videos and rooms using TypeORM.

5 — Configuring and running migrations

Now let’s write the script command in which the migrations will be generated. Go into your package.json file and write the following statement:

"scripts": {
"dev": "nodemon --exec ts-node ./src/index.ts",
"migration:generate": "typeorm-ts-node-commonjs -d ./src/data-source.ts migration:generate ./src/migrations/default",
"migration:run": "typeorm-ts-node-commonjs -d ./src/data-source.ts migration:run"
},

“migration:generate”: Creates database update instructions using TypeORM and a configuration file. Instructions are stored in a migrations folder.

“migration:run”: Runs the migration statements created earlier, updating the database as needed. It helps keep the database in sync with the application code.

Knowing this, run the command yarn run migration:generation to create the migration.

Here we have the migration:

After the created migrations, time to put it to run. Ride command yarn run migration:run

  • Mine appears this message because I already ran the command, in yours it will appear that the migration was completed

Looking at our database through a database manager, we will see the created tables, rooms and videos. As well as the migration table that holds information on which migrations were performed on the database.

Well, from now on you can start developing your project. I hope this article has helped or clarified some points regarding the technologies covered.

Code: https://github.com/Icegreeen/template_node

Thank you, any criticism, doubt or suggestion just leave it in the comments field below.

--

--

Icegreen
Icegreen

Written by Icegreen

🧑🏻‍💻 software engineer ⭐ creator of backseasy | backseasy.com 🛸 works: www.flavioaquila.com

No responses yet