In this blog post, I'll show you how to set up a project using TypeScript, Nest, Postgres, Docker and how to seed your database.
TypeScript is a statically typed language that is a strict syntactical superset of JavaScript. It offers improved type safety and tooling support, making it a popular choice for larger-scale projects.
Nest is a framework for building efficient, scalable Node.js server-side applications. It provides a structure and a range of features that make it easier to develop and test applications.
Postgres is a powerful open-source relational database management system that is well suited for complex data structures and large-scale data processing.
TypeORM is an open-source Object Relational Mapping (ORM) tool that provides a way to interact with relational databases such as MySQL, PostgreSQL, and SQLite. It helps you to write database-related code using object-oriented programming in TypeScript or JavaScript, instead of writing raw SQL statements. TypeORM offers a lot of features such as transaction management, database migrations, connection pooling, etc. that makes it easy to work with databases in your applications.
Docker is a containerization platform that makes it easier to deploy and run applications in different environments. We will launch a Postgres database and supporting service in docker.
Nest:
First, install nest-cli
npm i -g @nestjs/cli
Then, create a new project using the nest cli
nest new project-name
Choose: npm for package manager,
Next, enter in the project folder
cd project-name
PostgreSQL Database
Install pg
npm install pg --save
TypeORM
Install TypeOrm
npm install --save @nestjs/typeorm typeorm postgres
Open your project with your IDE
In the app.module.ts, add the connection to the databese with TypeOrmModule.forRoot():
// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'root',
password: 'password',
database: 'postgres',
entities: [`${__dirname}/typeorm/entities/*{.js,.ts}`],
synchronize: true, // do not use in prod
}),
],
})
export class AppModule {}
BTW: you can delete app.service and app.controller
Now, we should create our first module with nest cli:
nest g resource modules/users
choose REST API on terminal
select 'yes' to generate CRUD entry points
With the module created, we should now organize our project like this:
1) create some folders called: typeorm > database / entities / seeds
2) create data-source.ts, main.seed.ts and user.seed.ts
3) move the user entity to the entity folders
/src/typeorm
├── database
│ └── data-source.ts
├── seeds
│ └── main.seed.ts
└── entities
└── user.entity.ts *(generated by the script)*
insert the code bellow into the files:
// users.entity.ts
import { Column, CreateDateColumn, DeleteDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
@Entity('users')
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
email: string;
@Column()
active: boolean;
@Column()
birthday: Date;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@DeleteDateColumn()
deletedAt: Date;
}
// users.service.ts
import { Injectable } from '@nestjs/common';
import { User } from 'src/typeorm/entities/user.entity';
import { DataSource } from 'typeorm';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Injectable()
export class UsersService {
constructor(private dataSource: DataSource) {}
private userRepository = this.dataSource.getRepository(User);
async create(createUserDto: CreateUserDto) {
return this.userRepository.save(createUserDto);
}
async findAll(): Promise<User[]> {
return this.userRepository.find();
}
async findOne(id: number) {
return this.userRepository.findOneBy({ id });
}
async update(id: number, updateUserDto: UpdateUserDto) {
let user = await this.findOne(id);
user = { ...user, ...updateUserDto };
return await this.userRepository.save(user);
}
async remove(id: number) {
const user = await this.findOne(id);
return await this.userRepository.softRemove(user);
}
}
// data-source.ts
import { DataSource, DataSourceOptions } from 'typeorm';
export const dataSourceOptions: DataSourceOptions = {
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'root',
password: 'password',
database: 'postgres',
entities: ['src/**/*.entity{.js,.ts}'],
};
export default new DataSource(dataSourceOptions);
// main.seed.ts
import { DataSource } from 'typeorm';
import { dataSourceOptions } from '../database/data-source';
import { User } from '../entities/user.entity';
const dataSource = new DataSource(dataSourceOptions);
const userRepository = dataSource.getRepository(User);
async function connect() {
try {
if (dataSource.isInitialized) {
await dataSource.destroy();
}
await dataSource.initialize();
console.log('Data Source has been initialized!');
} catch (err) {
console.error('Error during Data Source connect', err);
}
}
async function disconnect() {
try {
await dataSource.destroy();
console.log('Data Source disconnected!');
} catch (err) {
console.error('Error during Data Source disconnect', err);
}
}
async function seed() {
const UserSeed = () => [
{
name: 'John Doe',
email: 'john@doe.com',
active: true,
birthday: '1990-01-01',
},
{
name: 'Jane Doe',
email: 'jane@doe.com',
active: false,
birthday: '1990-01-31',
},
{
name: 'Josh Doe',
email: 'josh@doe.com',
active: true,
birthday: '2020-12-31',
},
];
await userRepository.save(UserSeed());
console.log('created seeds');
}
async function runSeed() {
await connect();
console.log('connected');
await seed();
console.log('seed done');
await disconnect();
console.log('disconnected');
}
runSeed();
Now, we should create our 'docker-compose.yml' file in the root folder, and then run sudo docker-compose up
! Make sure the Docker is running in your system !
version: '3.1'
services:
db:
image: postgres:14.2-alpine
restart: always
environment:
POSTGRES_USER: "root"
POSTGRES_PASSWORD: "password"
POSTGRES_DB: "postgres"
ports:
- "5432:5432"
Some useful docker commands:
sudo docker ps
to list all containers
sudo docker stop my_container_name
to stop a specific container
Now, add a script to package.json
// package.json
"seed":"npx ts-node src/typeorm/seeds/main.seed.ts",
in a new terminal on the IDE run the code npm start
to synchronize the database
kill the application, and then run the script npm run seed
to populate the database
Its Done! now if you run npm start
and send a GET
request on localhost:3000/users
, you shold get all the users from the seed.
Top comments (4)
Amazing
Thank you
So clear and well explained!
Gj bro!
Thanks!!