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.