Executando verificação de segurança...
2

API com Nest + Typescript + TypeORM + Postgres + Docker

Neste post do blog, vou mostrar como configurar um projeto usando TypeScript, Nest, Postgres, Docker e como semear sua base de dados.

TypeScript é uma linguagem tipada estaticamente que é um superconjunto estrito da sintaxe do JavaScript. Oferece segurança de tipo aprimorada e suporte a ferramentas, tornando-se uma escolha popular para projetos de maior escala.

Nest é um framework para construir aplicações eficientes e escaláveis no lado do servidor com Node.js. Ele fornece uma estrutura e uma gama de recursos que facilitam o desenvolvimento e o teste de aplicações.

Postgres é um poderoso sistema de gerenciamento de banco de dados relacional de código aberto que é bem adequado para estruturas de dados complexas e processamento de dados em grande escala.

TypeORM é uma ferramenta de Mapeamento Objeto-Relacional (ORM) de código aberto que fornece uma maneira de interagir com bancos de dados relacionais como MySQL, PostgreSQL e SQLite. Ajuda você a escrever código relacionado a banco de dados usando programação orientada a objetos em TypeScript ou JavaScript, em vez de escrever instruções SQL brutas. O TypeORM oferece muitos recursos, como gerenciamento de transações, migrações de banco de dados, pooling de conexões, etc., que facilitam o trabalho com bancos de dados em suas aplicações.

Docker é uma plataforma de contêineres que facilita o deploy e a execução de aplicações em diferentes ambientes. Vamos lançar um banco de dados Postgres e serviço de suporte no docker.


Nest
Primeiro, instale o nest-cli
npm i -g @nestjs/cli
Depois, crie um novo projeto usando o nest cli
nest new nome-do-projeto
Escolha: npm para gerenciador de pacotes,
Em seguida, entre na pasta do projeto
cd nome-do-projeto


Banco de Dados PostgreSQL

Instale o pg
npm install pg --save


TypeORM

Instale o TypeORM
npm install --save @nestjs/typeorm typeorm postgres


Abra seu projeto com seu IDE

No app.module.ts, adicione a conexão com o banco de dados com 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: você pode deletar app.service e app.controller

Agora, devemos criar nosso primeiro módulo com o nest cli:

nest g resource modules/users

escolha REST API no terminal
selecione 'sim' para gerar pontos de entrada CRUD

Com o módulo criado, devemos agora organizar nosso projeto assim:

criar algumas pastas chamadas: typeorm > database / entities / seeds
criar data-source.ts, main.seed.ts e user.seed.ts
mover a entidade do usuário para as pastas de entidades

/src/typeorm
├── database
│ └── data-source.ts
├── seeds
│ └── main.seed.ts
└── entities
└── user.entity.ts (gerado pelo script)

insira o código abaixo nos arquivos:

// 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: '[email protected]',
      active: true,
      birthday: '1990-01-01',
    },
    {
      name: 'Jane Doe',
      email: '[email protected]',
      active: false,
      birthday: '1990-01-31',
    },
    {
      name: 'Josh Doe',
      email: '[email protected]',
      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();

Agora, devemos criar nosso arquivo 'docker-compose.yml' na pasta raiz, e então rodar

sudo docker-compose up

! Certifique-se de que o Docker está rodando em seu sistema !

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"

Alguns comandos úteis do docker:

sudo docker ps para listar todos os contêineres
sudo docker stop nome_do_meu_contêiner para parar um contêiner específico

Agora, adicione um script ao package.json

// package.json
"seed":"npx ts-node src/typeorm/seeds/main.seed.ts",

em um novo terminal no IDE rode o código npm start para sincronizar o banco de dados

mate a aplicação, e então rode o script npm run seed para popular o banco de dados

Pronto! Agora, se você rodar npm start e enviar uma requisição GET em localhost:3000/users, você deverá receber todos os usuários da semeadura.

Carregando publicação patrocinada...
1