Olá, bem-vindo ao terceiro post da série Como criar uma API REST com Nestjs!
Nessa etapa, vamos continuar o projeto que definimos no último post, conectando-o ao banco de dados e definindo as nossas entidades.
1 - Conectando o projeto ao banco de dados
Vamos começar criando um novo banco de dados no DBeaver, na conexão criada na etapa 1:

Nomeie o banco como my_pricing
e coloque como Owner o usuário root

Com o banco de dados criado, vamos conectar o projeto a ele. Para isso, utilizaremos o TypeORM, um módulo de gerenciamento de relações.
2 - Configurando a conexão do banco de dados no projeto
Primeiramente, no Visual Code, vamos instalar as dependências necessárias para integrar nosso projeto ao TypeORM:
yarn add @nestjs/typeorm typeorm
e
yarn add pg
Feita a instalação, vamos criar um arquivo ormconfig.json
na raiz do projeto, e nele colocar os dados da nossa conexão e configurar o diretório onde iremos armazenar as migrations que serão geradas ao longo do projeto:
{
"type": "postgres",
"host": "localhost",
"port": 5432,
"user": "root",
"username": "root",
"password": "root",
"database": "my_pricing",
"synchronize": false,
"logging": false,
"entities": [],
"migrations": [],
"cli": {
"migrationsDir": "/src/database/migrations"
}
}
Após configurar o arquivo, em app.module iremos importar o TypeOrmModule:

No arquivo package.json
, em scripts
, adicione o seguinte comando:
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js"
Feito! Nosso projeto está configurado com o banco de dados e poderemos agora criar as nossas entidades.
3 - Criando os modelos
Nesse projeto, tudo o que for relacionado ao banco de dados vamos armazenar em uma pasta database
dentro de src
. Crie também uma pasta models
e migrations
dentro da nossa pasta database
.
Agora vamos começar a criar os models de acordo com o diagrama abaixo:

User:
import { PrimaryGeneratedColumn, Column, Entity, OneToMany } from 'typeorm';
import { Order } from 'src/database/models/order.model';
import { Product } from 'src/database/models/product.model';
@Entity('user')
export class User {
@PrimaryGeneratedColumn({ name: 'id', type: 'bigint' })
id!: string;
@Column({ name: 'name', type: 'varchar' })
name!: string;
@Column({ name: 'email', type: 'varchar', unique: true })
email!: string;
@Column({ name: 'password', type: 'varchar', select: false })
password!: string;
@OneToMany(() => Product, (product) => product.user)
products: Product[];
@OneToMany(() => Order, (order) => order.user)
orders: Order[];
}
Input (Insumo):
import {
Column,
Entity,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Product } from 'src/database/models/product.model';
@Entity('input')
export class Input {
@PrimaryGeneratedColumn({ name: 'id', type: 'bigint' })
id!: string;
@Column({ name: 'name', type: 'varchar' })
name!: string;
@Column({
name: 'total_price',
type: 'decimal',
default: '0.00',
precision: 11,
scale: 2,
})
totalPrice!: string;
@Column({ name: 'used_percentage', type: 'int' })
usedPercentage!: string;
@Column({ name: 'product_id', type: 'bigint' })
productId!: string;
@ManyToOne(() => Product, (product) => product.inputs)
@JoinColumn({ name: 'product_id' })
product?: Product;
}
Product:
import {
Column,
Entity,
JoinColumn,
ManyToMany,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Input } from 'src/database/models/input.model';
import { Order } from 'src/database/models/order.model';
import { User } from 'src/database/models/user.model';
@Entity('product')
export class Product {
@PrimaryGeneratedColumn({ name: 'id', type: 'bigint' })
id!: string;
@Column({ name: 'name', type: 'varchar' })
name!: string;
@Column({
name: 'total_price',
type: 'decimal',
default: '0.00',
precision: 11,
scale: 2,
})
totalPrice!: string;
@Column({
name: 'inputs_price',
type: 'decimal',
default: '0.00',
precision: 11,
scale: 2,
})
inputsPrice!: string;
@Column({ name: 'profit_percentage', type: 'int' })
profitPercentage!: string;
@Column({ name: 'is_avaible', type: 'boolean' })
isAvaible!: boolean;
@OneToMany(() => Input, (input) => input.product)
inputs?: Input[];
@ManyToMany(() => Order, (order) => order.products, { cascade: true })
orders?: Order[];
@Column({ name: 'user_id', type: 'bigint' })
userId!: string;
@ManyToOne(() => User, (user) => user.products)
@JoinColumn({ name: 'user_id' })
user: User;
}
Order:
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
JoinTable,
ManyToMany,
ManyToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Product } from 'src/database/models/product.model';
import { User } from 'src/database/models/user.model';
@Entity('order')
export class Order {
@PrimaryGeneratedColumn({ name: 'order_id', type: 'bigint' })
id!: string;
@CreateDateColumn({ name: 'created_at', precision: 3 })
createdAt!: Date;
@Column({
name: 'total_price',
type: 'decimal',
default: '0.00',
precision: 11,
scale: 2,
})
totalPrice!: string;
@Column({
name: 'inputs_price',
type: 'decimal',
default: '0.00',
precision: 11,
scale: 2,
})
inputsPrice!: string;
@Column({ name: 'is_avaible', type: 'boolean' })
isAvaible!: boolean;
@ManyToMany(() => Product, (product) => product.orders)
@JoinTable({
name: 'order_product_order',
joinColumn: { name: 'order_id' },
inverseJoinColumn: { name: 'product_id' },
})
products?: Product[];
@Column({ name: 'user_id', type: 'bigint' })
userId!: string;
@ManyToOne(() => User, (user) => user.products)
@JoinColumn({ name: 'user_id' })
user: User;
}
Pronto! Com os models criados vamos agora criar um arquivo index.ts
no mesmo diretório para facilitar a exportação dessas classes:
import { Product } from 'src/database/models/product.model';
import { Order } from 'src/database/models/order.model';
import { Input } from 'src/database/models/input.model';
import { User } from 'src/database/models/user.model';
export const entities = [User, Input, Order, Product];
Vamos adicionar um index.ts
na pasta de migrations também:
export const migrations = [];
Não tem problema que nosso array de migrations esteja vazio por enquanto, vamos alimentá-lo no próximo passo.
Por fim, vamos voltar ao nosso arquivo ormconfig.json
na raiz do projeto e vamos adicionar os diretórios dos models
e das migrations
:
entities: ["src/database/models/index.ts"],
"migrations": ["src/database/migrations/index.ts"],
Feito isso, podemos seguir para a geração e execução da nossa migration!
4 - Gerando uma migration
Para gerar uma migration, basta executar o seguinte comando:
yarn typeorm migration:generate -n InitialMigration
Feito! Na nossa pasta de migrations deve existir um novo arquivo agora.
O último passo é importar esse arquivo no index da pasta de migrations e executar o comando a seguir:
yarn typeorm migration:run
Agora é só atualizar a conexão no DBeaver que você verá a estrutura do nosso banco já pronta!

Com o banco configurado vamos poder trabalhar com as requisições e começar a adicionar lógica no nosso projeto!
Aguardo você no próximo post!