Olá! Boas-vindas ao curso de NestJS com TypeORM. Eu sou o Daniel e serei seu instrutor durante essa jornada.
Daniel é um homem de 25 anos, de pele clara, cabelos encaracolados longos, olhos castanho-escuros e barba por fazer. Está de camiseta preta com a silhueta do gato do GitHub estampada ao centro e headphones. Ao fundo, o seu quarto: um quadro em branco, uma estante com enfeites e uma iluminação azul.
Esse curso faz parte da formação de NestJS. Então:
Esse último requisito é essencial, pois seguiremos com o projeto da loja, iniciado no primeiro curso, que trata de API Rest no NestJS e fundamentos do NestJS. Agora, basicamente, começaremos a salvar as informações de usuário e produto em um banco de dados.
Esse curso é para você que está começando no desenvolvimento back-end e no Node ou já possui um conhecimento mais aprofundado em programação e, talvez, esteja migrando de tecnologia e começando no NestJS.
É importante frisar que trabalharemos somente com back-end neste curso.
Observação: Caso você queira trabalhar com outro banco no seu projeto, fique à vontade. Porém, no curso, ofereceremos o suporte para trabalhar com o Postgres.
E aí, vamos nessa?!
Nos encontramos no próximo vídeo, adentrando esse cenário que traçamos agora.
Nessa sequência, começaremos a configuração do TypeORM no projeto. Mas, por que trabalharemos com TypeORM?
Considerando o curso inicial dessa informação, já temos o projeto da nossa loja. Nela, temos um cadastro de usuário e um cadastro de produto. Porém, hoje, essas informações não ficam persistidas em uma base de dados. O cadastro existe, mas é meramente ilustrativo - toda vez que fechamos a nossa aplicação, perdemos essas informações.
A ideia, então, é conseguir salvar essas informações no banco de dados. Para isso, trabalharemos com o conceito de ORM e, no NestJS, trabalharemos com o TypeORM: uma biblioteca que facilita a nossa integração com o banco de dados por meio de comandos do SQL.
Para começar a configuração, nós abrimos o nosso projeto no VSCode. Basta clicar em "Arquivo > Abrir Pasta" e selecionar a pasta do projeto em que estamos trabalhando.
No menu Explorador, à esquerda da tela, e clicando na pasta "src", podemos observar que temos a mesma estrutura de projeto do curso anterior:
src
- produto
- usuario
- app.module.ts
- main.ts
Começaremos a mexer tanto no módulo de "produto" quanto de "usuário", mas antes precisamos configurar o TypeORM.
Clicando em package.json
, notamos que ainda não possuímos nenhuma dependência do TypeORM. Então, para começar, precisamos adicionar as bibliotecas do TypeORM no nosso projeto.
Faremos isso por um terminal, que fica à sua escolha. Aqui utilizaremos o terminal do próprio VSCode, abrindo-o pelo atalho "Ctrl + ’ ", que já inicializa dentro do diretório de trabalho - no caso, a pasta "loja".
Utilizaremos o seguinte comando:
npm install @nestjs/typeorm typeorm
Após digitar, pressionamos "Enter". Estamos adicionando duas bibliotecas no código, utilizando a notação do TypeScript para o TypeORM e, também, o TypeORM.
É normal demorar um tempo até a adição das bibliotecas ser concluída. Quando concluir, podemos fechar o terminal para limpar a tela.
Em seguida, abrimos o arquivo package.json
no menu Explorador. Podemos notar que agora, na seção de "dependencies"
, temos tanto o typeorm
quanto o @nestjs/typeorm
, a notação do TypeScript utilizando o NestJS.
Temos a biblioteca do TypeORM no projeto. Feito isso, começaremos a configurá-lo.
Clicaremos na pasta "src" no menu Explorador com o botão direito do mouse e, em seguida, em "Nova Pasta…". Podemos chamá-la de "config", porque é nela que configuraremos o TypeORM.
Agora, clicamos nessa nova subpasta com o botão direito e, depois, em "Criar Arquivo…". O nome desse novo arquivo pode tanto seguir o nome do banco de dados com que trabalharemos como ser um nome genérico, por exemplo "db.config.service.ts
".
No nosso caso, estamos trabalhando com o Postgres, um banco de dados comumente utilizado. Então, nomearemos esse arquivo como "postgres.config.service.ts
". Tanto o banco de dados a ser utilizado quanto o nome do arquivo ficam a seu critério.
Pronto! Temos nosso arquivo inicial dentro da pasta "config".
Observação: Precisamos nos restringir a um domínio, e criar esse arquivo fora da pasta não seria uma boa prática.
Nesse arquivo, antes de tudo, exportaremos a classe PostgresConfigService
, conforme o nome do arquivo. Ela vai implementar o TypeOrmOptionsFactory
, opção que podemos selecionar pelo autocomplete do VSCode, já que já possuímos a biblioteca.
Ao fazer isso, é feita a importação automática TypeOrmOptionsFactory
. Caso isso não aconteça na sua máquina, basta importar manualmente. Então, nosso código fica assim:
postgres.config.service.ts
import { TypeOrmOptionsFactory } from '@nestjs/typeorm';
export class PostgresConfigService implements TypeOrmOptionsFactory {
}
Já podemos criar uma função dentro dessa classe, que será a função createTypeOrmOptions
. Ou seja, criaremos algumas opções para o nosso TypeORM conseguir se conectar com o banco de dados. Vamos tipar essa função como TypeOrmModuleOptions
, que também será importado automaticamente, e inserir um retorno:
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
export class PostgresConfigService implements TypeOrmOptionsFactory {
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
}
}
}
Essa função nos retornará as configurações do banco, informações primordiais para conseguirmos nos conectar a ele. Então, passamos os seguintes parâmetros:
type
: qual é o banco;host
: onde esse banco está;port
: qual porta do host está aberta para esse banco, executando seu processo;username
: nome de usuário;password
: senha;database
: banco que queremos acessar do host;entities
: entidades. Esse parâmetro ficará vazio por enquanto, mas já o deixaremos aqui para, no futuro, preencher e não precisarmos mais adicionar informações nessa função;synchronize
: opção de sincronização automática para nunca perdermos a conexão - a definimos como true
.Agora, preencheremos essas configurações conforme o banco. Nós não temos o banco ainda, então vamos inserir algumas informações de exemplo apenas para o VSCode parar de reclamar os erros.
A primeira informação é o type
. Se escrevermos uma aspa simples, '
, receberemos várias sugestões de types. Só conseguimos utilizar o que estão nessas opções. O type
é escolhido conforme o SGBD que queremos utilizar. Por exemplo, temos o mysql
, o mongodb
, e assim por diante. Estamos trabalhando com o Postgres; portanto, escrevemos 'postgres'
.
O host
é sempre dado como string, e podemos colocar como exemplo ilustrativo '127.0.0.1'
. A porta pode ser 5432
; o nome de usuário e senha podem ser 'root'
; o banco será 'loja'
.
Por fim, podemos anotar esse arquivo como @Injectable()
no topo, logo acima da exportação da classe. Em seguida, realizamos a sua importação do @nestjs/common
.
A classe, com a função e retorno, ficará assim:
import { Injectable } from '@nestjs/common';
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
@Injectable()
export class PostgresConfigService implements TypeOrmOptionsFactory {
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
type: 'postgres',
host: '127.0.0.1'
port: 5432
username: 'root'
password: 'root'
database: 'loja'
entities: [],
synchronize: true,
};
}
}
Talvez você tenha alguns erros apontados nos espaços em branco da indentação, relacionados com o
eslint
. Não precisamos nos preocupar com isso no momento, pois esses erros não têm relação com o que escrevemos.
Temos as informações do nosso banco de dados, a entidade que por enquanto está nula, e a opção de sincronização ativa. Esse arquivo está parcialmente resolvido!
Lembrando que não temos nenhum banco ainda, por isso essas informações são meramente fictícias. Criaremos um banco num momento oportuno.
Para finalizar essa configuração, clicamos no arquivo app.module.ts
no menu Explorador, dentro da "src".
Temos um import de UsuarioModule
e ProdutoModule
nesse arquivo. Vamos quebrar essa linha, organizando esses imports em lista, e chamar uma nova importação: TypeOrmModule.forRootAsync({})
. Dentro das chaves, colocamos um useClass
, chamando a classe que acabamos de criar: PostgresConfigService
.
Também podemos colocar um inject
da mesma classe, pois estamos usando um @Injectable
nela:
app.module.ts
import { Module } from '@nestjs/common';
import { ProdutoModule } from './produto/produto.module';
import { UsuarioModule } from './usuario/usuario.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { PostgresConfigService } from './config/postgres.config.service';
@Module({
imports: [
UsuarioModule,
ProdutoModule,
TypeOrmModule.forRootAsync({
useClass: PostgresConfigService,
inject: [PostgresConfigService],
}),
],
})
export class AppModule {}
Pronto! Temos a configuração do TypeORM.
Claro, se rodarmos a aplicação agora, ela vai dar erro. Isso porque não temos nenhum banco no endereço fictício que indicamos em postgres.config.service.ts
. Mas isso não é problema, porque somente criamos a configuração para criar o banco em um segundo momento.
É isso! Até mais.
No vídeo anterior, nós concluímos a configuração do TypeORM: já temos a classe de configuração para nos conectar ao banco, a postgres.config.service.ts
, e também já configuramos o app.module.ts
.
Mas, agora temos um detalhe referente às boas práticas. Estamos colocando informações sensíveis no meio do código: o nome de usuário (username
) e a senha (password
) do banco de dados.
Não é interessante que essas informações fiquem expostas no código, porque, por exemplo, subiremos esse repositório no GitHub - um local público. Ou seja: outra pessoa pode abrir esse repositório, ver o nome de usuário, senha e até o host, caso estivéssemos com o banco na nuvem, e acessá-lo.
O ideal, nesse caso, é trabalhar com variáveis de ambiente para não deixar informações sensíveis soltar no meio do código. É isso que faremos nesse vídeo!
Para isso, precisamos instalar uma biblioteca: @nestjs/config
, um módulo do NestJS.
Acionamos o terminal novamente, dentro do projeto "loja", e rodamos o seguinte comando:
npm install @nestjs/config
Ao terminar a instalação, fechamos o terminal. Realizaremos a configuração no arquivo app.module.ts
novamente, o mesmo arquivo que colocamos o TypeOrmModule
, que servirá para inicializar o módulo de configuração.
Podemos criar uma linha depois de ProdutoModule
e chamar a função que será ConfigModule.forRoot({})
. Dentro das chaves, colocamos o isGlobal: true
para setar o ConfigModule
como global. Também devemos importar o ConfigModule
, a biblioteca que instalamos anteriormente.
Nosso arquivo ficará assim:
import { Module } from '@nestjs/common';
import { ProdutoModule } from './produto/produto.module';
import { UsuarioModule } from './usuario/usuario.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';
import { PostgresConfigService } from './config/postgres.config.service';
@Module({
imports: [
UsuarioModule,
ProdutoModule,
ConfigModule.forRoot({
isGlobal: true,
}),
TypeOrmModule.forRootAsync({
useClass: PostgresConfigService,
inject: [PostgresConfigService],
}),
],
})
export class AppModule {}
A configuração está, basicamente, preparada, e já a temos a nível global, então salvamos o arquivo com "Ctrl + S".
O que precisamos agora é que o nosso arquivo de configuração do Postgres consiga utilizar essa configuração para podermos remover isso do arquivo de configuração do Postgres.
No menu Explorador, clicamos em "src > config > postgres.config.service.ts
".
Para conseguirmos utilizar o módulo nesse arquivo, utilizamos um construtor na nossa classe. Criamos uma linha abaixo da exportação da classe e digitamos constructor()
.
A ideia do construtor é ter uma execução assim que a nossa classe for importada no app.module
. Em outras palavras, quando ela for importada, queremos que o que estiver no construtor seja executado.
Dentro desse construtor, criaremos uma variável com private
, chamada configService
. Sua tipagem será ConfigService
, cuja importação vem da biblioteca @nestjs/config
que instalamos anteriormente. Depois, abrimos e fechamos chaves para que o erro do construtor suma:
postgres.config.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
@Injectable()
export class PostgresConfigService implements TypeOrmOptionsFactory {
constructor(private configService: ConfigService) {}
// código omitido
A partir disso, já conseguimos utilizar as configurações do próprio ConfigService
.
Então, podemos utilizar essas configurações no host
da seguinte maneira: digitamos this.configService.get<string>('')
, pois queremos pegar um valor do tipo string. Passaremos como parâmetro a referência para pegar esse valor. Então:
host: this.configService.get<string>('')
Faremos isso com todos os outros campos. Podemos copiar essa linha e colar para todos os parâmetros, apenas mudando o tipo string
para number
na porta, porque o valor desse campo é numérico, resultando em:
postgres.config.service.ts
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
type: 'postgres',
host: this.configService.get<string>(''),
port: this.configService.get<number>(''),
username: this.configService.get<string>(''),
password: this.configService.get<string>(''),
database: this.configService.get<string>(''),
entities: [''],
synchronize: true,
};
}
}
Fizemos 50% da configuração. Agora, precisamos referenciar os valores que queremos buscar.
Para isso, voltamos ao Explorador e clicamos com o botão direito na pasta "loja" (fora de "src") e, em seguida, em "Novo Arquivo...". Vamos nomear esse novo arquivo como .env
(pronunciado "dot env" ou "ponto env"), e será nele que nossas configurações ficarão.
Então, por exemplo: no arquivo postgres.config.service
, tínhamos o host
definido como 127.0.0.1
. Essa informação não vai ficar mais nesse arquivo, mas no .env
. Esse arquivo, por boas práticas, não é enviado para o GitHub. Ou seja, a informação só existe localmente na máquina.
Então, criaremos as referências nele. Como:
.env
DB_HOST=127.0.0.1
Agora, para referenciá-lo, basta voltar no arquivo postgres.config.service
e colocar a referência como string entre os parênteses:
postgres.config.service.ts
host: this.configService.get<string>('DB_HOST')
Ou seja: queremos que o configService
leia o arquivo .env
, um arquivo padrão, onde temos o DB_HOST
, chave cujo valor é 127.0.0.1
, agora não mais fixo no código.
Agora, só precisamos seguir a mesma lógica para os outros valores:
.env
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=root
DB_PASSWORD=root
DB_NAME=loja
Usamos todas as informações de antes, criando as chaves com nomes comumente utilizados por boa prática. Porém, podemos definir outros nomes caso seja necessário.
O importante é que o nome definido seja o mesmo referenciado no arquivo de configuração do banco.
Agora, inserimos as referências:
postgres.config.service.ts
// código omitido
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
type: 'postgres',
host: this.configService.get<string>('DB_HOST'),
port: this.configService.get<number>('DB_PORT'),
username: this.configService.get<string>('DB_USERNAME'),
password: this.configService.get<string>('DB_PASSWORD'),
database: this.configService.get<string>('DB_NAME'),
entities: [],
synchronize: true,
};
}
Um último detalhe interessante: vamos verificar se o arquivo .env
consta em .gitignore
. Se pressionarmos "Ctrl + F" e digitarmos ".env" na barra de busca, não teremos nenhum resultado.
Precisamos adicioná-lo, porque esse arquivo não vai para o GitHub por uma questão de segurança. Estando no arquivo .gitignore
, ele será ignorado no upload para o repositório público. No fim do arquivo, então, digitamos:
.gitignore
// omitido
.env
Para finalizar, vamos executar o projeto e entender os erros atuais para traçar nossos próximos passos. Para tanto, abrimos novamente o terminal e rodamos o seguinte comando dentro da pasta "loja":
npm start
Automaticamente, receberemos algumas reclamações. Por exemplo:
Postgres package has not been found installed.
Ou seja, o pacote do Postgres não está instalado. A sugestão dada é rodar o seguinte comando:
npm install pg
O pg
é o módulo do Postgres. No nosso arquivo postgres.config.service.ts
, estamos usando utilizando o postgres
como tipo do banco. Para isso, é necessário que o nosso projeto conheça o Postgres. Por isso o erro foi apontado e foi pedida a instalação - e isso aconteceria com qualquer outro banco.
Então, vamos rodar o comando acima para finalizar essa configuração. É um pacote bem enxuto e de instalação rápida. Ao finalizar, podemos tentar executar nosso projeto novamente com npm start
.
O próximo erro apontado é:
Password authentication failed for user "root".
Já prevíamos esse erro, que acontece porque não temos o servidor do Postgres. A partir dos próximos vídeos, veremos um pouco mais sobre ORM e começaremos a realizar a correção desse problema criando, de fato, um banco de dados.
Até lá!
O curso Nest.js: Persistindo dados com TypeORM e PostgreSQL possui 170 minutos de vídeos, em um total de 45 atividades. Gostou? Conheça nossos outros cursos de Node.JS em Programação, ou leia nossos artigos de Programação.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.