Aluizio Developer

Atualizando o TypeORM na API de Vendas

Descrevendo as principais alterações na API de Vendas a partir do release 0.3.0 do TypeORM.

Em meados do mês de março de 2022 o projeto do TypeORM lançou o Release 0.3.0 dessa excelente ferramenta, com bastante modificações na maneira de implementar, em comparação com a release anterior.

Visite o meu perfil no portal da Udemy e conheça os cursos disponibilizados.

Neste post estarei trazendo as questões mais relevantes dessa nova versão do TypeORM considerando as demandas da API de Vendas, projeto do curso API Restful Javascript com Node.js, Typescript, TypeORM etc.

É extremamente importante que leiam o Changelog da versão 0.3.0, pois aqui neste post será abordado apenas as funcionalidades necessárias para a refatoração da nossa API.

Conexão e configuração

Essa nova versão do TypeORM não precisa do arquivo ormconfig.json para se conectar ao banco de dados. Podemos excluir esse arquivo.

Para criar a conexão com o Postgres, deve-se exportar uma variável contendo uma instância da classe DataSource do TypeORM com as dados para a conexão.

O uso de string com o caminho indicando o local das entitiesmigrations está como depreciado e será removido nas versões futuras, por isso o ideal é importar e indicar diretamente cada classe de entitiesmigrations.

Exemplo do arquivo src/shared/infra/typeorm/index.ts.

import { DataSource } from 'typeorm';

import User from '@modules/users/infra/typeorm/entities/User';
import UserToken from '@modules/users/infra/typeorm/entities/UserToken';
import Customer from '@modules/customers/infra/typeorm/entities/Customer';
import Order from '@modules/orders/infra/typeorm/entities/Order';
import OrdersProducts from '@modules/orders/infra/typeorm/entities/OrdersProducts';
import Product from '@modules/products/infra/typeorm/entities/Product';

import { CreateProducts1607437608841 } from './migrations/1607437608841-CreateProducts';
import { CreateUsers1607534203339 } from './migrations/1607534203339-CreateUsers';
import { CreateUserTokens1607917238905 } from './migrations/1607917238905-CreateUserTokens';
import { CreateCustomers1608058533060 } from './migrations/1608058533060-CreateCustomers';
import { CreateOrders1609036872019 } from './migrations/1609036872019-CreateOrders';
import { AddCustomerIdToOrders1609037132700 } from './migrations/1609037132700-AddCustomerIdToOrders';
import { CreateOrdersProducts1609038202583 } from './migrations/1609038202583-CreateOrdersProducts';
import { AddOrderIdToOrdersProducts1609038414735 } from './migrations/1609038414735-AddOrderIdToOrdersProducts';
import { AddProductIdToOrdersProducts1609038674490 } from './migrations/1609038674490-AddProductIdToOrdersProducts';
import { AddOrderFieldtoOrders1619889809717 } from './migrations/1619889809717-AddOrderFieldtoOrders';

export const dataSource = new DataSource({
  type: 'postgres',
  host: 'db',
  port: 5432,
  username: 'postgres',
  password: 'docker',
  database: 'apivendas',
  entities: [User, UserToken, Customer, Order, OrdersProducts, Product],
  migrations: [
    CreateProducts1607437608841,
    CreateUsers1607534203339,
    CreateUserTokens1607917238905,
    CreateCustomers1608058533060,
    CreateOrders1609036872019,
    AddCustomerIdToOrders1609037132700,
    CreateOrdersProducts1609038202583,
    AddOrderIdToOrdersProducts1609038414735,
    AddProductIdToOrdersProducts1609038674490,
    AddOrderFieldtoOrders1619889809717,
  ],
});

Refatorar o arquivo server.ts para rodar o app

Para facilitar a criação da instância do servidor Node.js com o DataSource do TypeORM, vamos separar o conteúdo do arquivo server.ts criando o arquivo app.ts para conter toda a configuração do Express com os respectivos middlewares. Dessa forma, o arquivo server.ts ficará responsável apenas por instanciar o servidor.

Exemplo do arquivo src/shared/infra/http/app.ts:

import express, { NextFunction, Request, Response } from 'express';
import 'express-async-errors';
import cors from 'cors';
import { errors } from 'celebrate';
import { pagination } from 'typeorm-pagination';
import routes from './routes';
import AppError from '@shared/errors/AppError';
import '@shared/container';
import uploadConfig from '@config/upload';
import rateLimiter from '@shared/infra/http/middlewares/rateLimiter';

const app = express();
app.use(cors());
app.use(express.json());
app.use(rateLimiter);
app.use(pagination);
app.use('/files', express.static(uploadConfig.directory));
app.use(routes);
app.use(errors());
app.use(
  (error: Error, request: Request, response: Response, next: NextFunction) => {
    if (error instanceof AppError) {
      return response.status(error.statusCode).json({
        status: 'error',
        message: error.message,
      });
    }
    console.log(error);
    return response.status(500).json({
      status: 'error',
      message: 'Internal server error',
    });
  },
);

export { app };

Exemplo do arquivo src/shared/infra/http/server.ts refatorado:

import 'reflect-metadata';
import 'dotenv/config';
import { app } from './app';
import { dataSource } from '../typeorm';

dataSource.initialize().then(() => {
  const server = app.listen(3333, () => {
    return console.log('Server started on port 3333! 🏆');
  });
});

Usando a nova CLI do TypeORM

O processo de criação de arquivos de migrations também está diferente, agora é necessário informar o caminho completo do local para armazenar cada migration. Exemplo:

npm run typeorm migration:create src/shared/infra/typeorm/migrations/CreateTestsTable

Para executar o comando migration:run ou migration:revert, é necessário informar o caminho do arquivo com a instância da classe DataSource através dos parâmetros -d ou --dataSource. Exemplo:

npm run typeorm -- -d ./src/shared/infra/typeorm/index.ts migration:run

Refatorando os Repositórios

Para utilizar os repositórios com a nova versão do TypeORM, deve-se chamar o método getRepository() da instância do DataSource.

Para isso, basta importar o dataSource da configuração do TypeORM e utilizar o método dataSource.getRepository() passando a entidade como parâmetro. Exemplo:

import dataSource from "@shared/infra/typeorm";
import { User } from "../entities/User";

const usersRepository = dataSource.getRepository(User);

Agora, ao invés de usar o método findOne para as buscas por registro específico, devemos utilizar o método findOneBy, passando um objeto de configurações com a condição a ser realizada. Exemplo:

const user = await this.repository.findOneBy({ id });

Acesse a página do Release 0.3.0 para conhecer todas as mudanças a partir dessa nova versão do TypeORM.

Vamos em frente e até a próxima!

Comentários