API with Typescript + Nest + TypeORM + Postgres + Docker
Tags: nest, typescript, postgres, docker
Published: 2023-03-21 17:17:42

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.