Guia do framework NestJS \| TreinaWeb               Promoção no ar   Matricule-se agora e garanta **54% de desconto**  

  Termina em   Tempo restante da oferta: 06 Horas 

 13 Min 

 50 Seg 

   Tempo restante da oferta: 06 13 50 

  [Assinar →](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26) 

   [                ](https://www.treinaweb.com.br)  Explorar  

 [ Quanto custa? ](#assinatura) [ FAQ ](https://www.treinaweb.com.br#faq) [Matricule-se](#assinatura) [ Entrar ](https://www.treinaweb.com.br/login) 

     [ Início ](https://www.treinaweb.com.br) [ Artigos ](https://www.treinaweb.com.br/blog) Guia do framework NestJS  [ Desenvolvimento Back-end ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-back-end) [ Node ](https://www.treinaweb.com.br/blog/categoria/node-js) [ Guias ](https://www.treinaweb.com.br/blog/categoria/guias) 

# Guia do framework NestJS

 Neste guia do framework NestJS vamos fazer um compilado de tópicos úteis sobre o framework, desde criar um projeto básico até autenticação.

 [ Wesley Gado ](https://www.treinaweb.com.br/blog/autor/wesley-gado) 3 anos atrás

  ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/05/NEST-JS-UPLOAD-ARQUIVOS.png)  

Neste guia completo veremos como utilizar o NestJS para criar aplicações back-end e fullstack de forma prática.

## O que é o NestJS

O NestJS é um framework back-end que auxilia o desenvolvimento de aplicações [Node.js](https://nodejs.org/dist/latest-v18.x/docs/api/ "Node.js"), ele utiliza como padrão o [TypeScript](https://www.treinaweb.com.br/blog/como-instalar-o-typescript "TypeScript") e possui uma sintaxe familiar ao [Angular](https://www.treinaweb.com.br/blog/o-que-e-o-angular-e-para-que-serve "Angular"). Por padrão, trabalha com o [Express](https://www.treinaweb.com.br/blog/o-que-e-o-express-js "Express"), mas também trás a possibilidade de trabalhar com o [Fastfy](https://fastify.dev/docs/latest/ "Fastfy"), tornando mais prático o desenvolvimento de aplicações eficientes, escaláveis e robustas.

[  ![TypeScript - Fundamentos](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/typescript.svg)   Curso TypeScript - Fundamentos Conhecer o curso ](https://www.treinaweb.com.br/curso/typescript-fundamentos)

## Criando um projeto NestJS

Para criar um projeto NestJS é necessário termos o ambiente Node.js instalando e configurado em nossa máquina, você pode consultar um passo a passo de Instalação do Node.js no artigo: [Node.js - Windows, Mac e Linux](https://www.treinaweb.com.br/blog/instalacao-do-node-js-windows-mac-e-linux).

Com o ambiente Node.js configurado, podemos instalar a ferramenta NestCLI, que irá auxiliar na criação de projetos e arquivos, com o seguinte comando:

```tsx
npm i -g @nestjs/cli

```

Após a instalação, para criar efetivamente um projeto, vamos executar o comando:

```tsx
nest new nome-do-projeto

```

Desta forma teremos a estrutura de um projeto base iniciado para começar o desenvolvimento de uma aplicação utilizando o NestJS, com uma estrutura similar a imagem abaixo:

![Estrutura NestJS](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/07/estruturanestjs.png)

Para executar um projeto NestJS basta utilizar o comando:

```
npm run start:dev

```

E acessar localhost:3000 (porta padrão) para acessar a aplicação.

Mais detalhes podem ser consultados em nosso artigo “[O que é NestJS?](https://www.treinaweb.com.br/blog/o-que-e-nestjshttps://www.treinaweb.com.br/blog/o-que-e-nestjs)”

## Criando primeiro CRUD com NestJS

Para criar o primeiro CRUD com NestJS, vamos criar um projeto conforme o comando acima, veja que temos a estrutura igual aos arquivos da imagem acima, desta forma teremos alguns arquivos e camadas que serão respectivos a:

- **Entity:** são os modelos da aplicação que irão espelhar as tabelas do banco de dados;
- **Controller**: é a camada responsável pelas rotas, respostas e requisições;
- **Service**: é a camada responsável pela aplicação das regras de negócio;
- **Repository**: é a camada responsável pela comunicação com o banco de dados.

Podemos utilizar o comando `nest g res users --no-spec` para criar os arquivos responsáveis por cada responsabilidade automaticamente, neste caso, onde teremos um recurso referente a usuários. A flag `--no-spec` é utilizada para não gerar os arquivos de teste, que no momento não serão utilizados.

### Definindo entidade

Para difnir uma entidade, vamos localizar o arquivo `user.entity.ts`, neste arquivo podemos adicionar as propriedades que serão mapeadas para colunas respectivamente no banco de dados, um exemplo seria:

```tsx
export class User {
  id: number;
  nome: string;
  idade: number;
}

```

Agora, o próximo passo é configurar o [TypeORM](https://typeorm.io/ "TypeORM"), que será o [ORM](https://www.treinaweb.com.br/blog/o-que-e-orm "ORM") utilizado neste exemplo, onde fará o papel de espelhar a entidade para o Banco de Dados, para isto, vamos executar o comando de instalação:

```tsx
npm i @nestjs/typeorm typeorm sqlite3

```

Veja que instalamos o TypeORM e o SQLite. Após a instalação podemos adaptar a entidade para que o TypeORM consiga identificar a entidade e as propriedades:

```tsx
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn('increment')
  id: number;

  @Column()
  nome: string;

  @Column()
  idade: number;
}

```

Em seguida será necessário criar um arquivo de configuração, nomeado aqui de `ormconfig.ts` onde vamos apontar o banco de dados que será utilizado, os dados de acesso e onde estarão as entidades:

```tsx
import { DataSourceOptions } from 'typeorm';

export const config: DataSourceOptions = {
  type: 'sqlite',
  database: '.db/sql',
  synchronize: true, // Obs: use synchronize: true somente em desenvolvimento.
  entities: [__dirname + '/**/*.entity{.ts,.js}'],
};

```

Por útimo, é necessário importar no módulo de usuário que estamos utilizando o TypeORM:

```tsx
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UsersModule } from './users/users.module';
import { config } from './ormconfig';

@Module({
  imports: [UsersModule, TypeOrmModule.forRoot(config)],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

```

### Desenvolvendo o CRUD (create, read, update, delete)

Primeiramente devemos atualizar o arquivo `create-user.dto` que foi criado pelo NestCLI, lembrando que ele terá somente as propriedades nome e idade, pois o id será gerado automaticamente pelo banco:

```tsx
export class CreateUserDto {
  nome: string;
  idade: number;
}

```

#### Create - cadastro de usuários

Agora podemos desenvolver a função ‘create’, ou seja. vamos cadastrar um novo usuário, de acordo com os padrões de uma API REST e do protocolo HTTP, é utilizado o verbo HTTP POST. Portanto, vamos configurar os arquivos responsáveis pelo controller, service e repositório.

Controller:

```tsx
@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }
}

```

Service e Repositório:

```tsx
@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository,
  ) {}

  create(createUserDto: CreateUserDto) {
    return this.userRepository.save(createUserDto);
  }
}

```

Ao fazer uma requisição para esta rota passando um JSON no corpo da requisição referente ao usuário, será efetuado o cadastro e retornado o usuário cadastrado: ![criando usuario](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/07/criando-usuario.png)

#### Update - Atualização de usuários

Para atualizar um registro podemos utilizar o método PUT (atualizar todo o registro), ou PATCH (atualização parcial do registro), neste caso vamos utilizar a rota PATCH. Vale ressaltar que o arquivo `uptade-user.dto` está estendendo o arquivo `create-user.dto`, portanto, não será necessario atualiza-lo já que não teremos nenhuma alteração em relação as propriedades do registro. Desta forma, teremos os seguintes métodos que serão adicionados nas camadas de controller, service e repositório:

Controller

```tsx
@Patch(':id')
update(@Param('id') id: number, @Body() updateUserDto: UpdateUserDto) {
  return this.usersService.update(id, updateUserDto);
}

```

Service e repositório:

```tsx
update(id: number, updateUserDto: UpdateUserDto) {
    return this.userRepository.update(id, updateUserDto);
}

```

![Retorno da rota patch atualizando usuário](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/07/atualizando-usuario-1.png)

[  ![TypeScript - Avançado](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/typescript.svg)   Curso TypeScript - Avançado Conhecer o curso ](https://www.treinaweb.com.br/curso/typescript-avancado)

#### Read - Busca e Lista de usuários

Podemos buscar um registro ou listar todos os registros. Para isto vamos implementar duas rotas utilizando método http GET, onde uma irá simplesmente retornar todos os usuários, entretanto, a outra irá retornar somente um registro, que será referente ao ID do registro que vamos passar na URL.

Controller:

```tsx
@Get()
findAll() {
  return this.usersService.findAll();
}

@Get(':id')
findOne(@Param('id') id: number) {
  return this.usersService.findOne(id); //veja que vamos receber o id na rota e 
}                                       //passar como parametro no método findOne

```

Service e repositório:

```tsx
findAll() {
  return this.userRepository.find();
}

findOne(id: number) {
  return this.userRepository.findOneBy({ id: id }); //veja que passamos o id
}                                                   //para buscar o registro

```

Neste caso podemos observar o retorna da lista de usuários: ![Retorno da lista de registos](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/07/lista-de-registros.png)

E da buscar por um único registro: ![Retorno da busca única de registro](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/07/busca-unica-de-registro.png)

Vale salientar que para fazer a busca pela lista será pela rota GET “http://localhost:3000/users”, e para buscar por ID será pela rota GET “http://localhost:3000/users/1”, sendo 1 o ID respectivo ao usuário a ser consultado.

#### Delete - excluir usuários

E por último, vamos implementar a função de excluir um registro, onde utilizamos o método HTTP DELETE.

Controller:

```tsx
@Delete(':id')
remove(@Param('id') id: number) {
  return this.usersService.remove(id);
}

```

Service e repisório:

```tsx
remove(id: number) {
  return this.userRepository.delete(id);
}

```

Retorno da exclusão de registro: ![Retorno da exclusão de registro](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/07/deletando-registro.png)

A rota utilizada para excluir o registro será a rota DELETE “http://localhost:3000/users/1”, sendo 1 o ID respectivo ao registro a ser excluído.

E a base de um CRUD simples está concluída, caso você se interesse em se aprofundar na criação desse CRUD temos o artigo dedicado somente a este exemplo em [criando o primeiro CRUD com NestJS](https://www.treinaweb.com.br/blog/criando-o-primeiro-crud-com-nestjs).

## Validação e Serialização

Outro ponto impontante quando estamos desenvolvendo uma aplicação é validar os dados que serão enviados para a aplicação e parsear esse dados quando necessário. No NestJS temos dois pacotes que nos ajudam a trabalhar com esses recursos, sendo eles o class-validator e class-transformer.

Para instalar esses pacotes, basta executar o seguinte comando:

```bash
npm i class-validator class-transformer

```

### Class Validator

Uma forma simples e eficiente de utilizar o class-validator é através da utilização de decorators para validar as propriedades de um objeto, vamos ver um exemplo utilizando no arquivo `create-user.dto`, que será a classe responsável por transportar os dados da requisição até a persistencia do objeto em si no banco, veja um exemplo:

```tsx
import { IsNotEmpty, Length } from 'class-validator';

export class CreateUserDto {
  @IsNotEmpty({ message: 'Nome não pode ser vazio' })
  @Length(3, 10, { message: 'Nome precisa ter entre 3 e 10 caracteres' })
  nome: string;

  @IsNotEmpty()
  idade: number;
}

```

Veja que utilizamos o decorator `@IsNotEmpty()` para verificar se a propriedade nome é vazia. nula ou indefinida. Caso positivo, exibirá a mensagem que a propriedade não pode ser vazia.

Basicamente as validações seguirão esse padrão, um decorator que irá fazer a validação com um nome intuitivo e com a possibilidade de receber parametros e opções, como mensagens personalizadas, ou definir qual padrão de modelo de data para uma propriedade `Date`, por exemplo.

Vale salientar que devemos configurar no `main.ts` a utilização da validação de forma global:

```tsx
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe()); //devemos passar essa configuração
  await app.listen(3000);
}
bootstrap();

```

### Class Transformer

Agora podemos utilizar o class-transformer para manipular essa informação, por exemplo, vamos imaginar um cenário que os nomes devem estar todos com letras minúsculas, para isso podemos usar o decorator `@Transform()` nos DTOs, conforme abaixo:

```tsx
import { Transform } from 'class-transformer';
import { IsNotEmpty, Length, Validate } from 'class-validator';
import { IdadeValida } from '../validator-idade';

export class CreateUserDto {
  @IsNotEmpty({ message: 'Nome não pode ser vazio' })
  @Length(3, 10, { message: 'Nome precisa ter entre 3 e 10 caracteres' })
  @Transform(({ value }) => value.toLowerCase())
  nome: string;

  @IsNotEmpty()
  @Validate(IdadeValida)
  idade: number;
}

```

Utilizamos o decorator `@Transform()` para converter todos os caracteres da propriedade nome em letras minusculas. Outro ponto também é que podemos utilizar os recursos `@Exclude()` e `@Expose()` onde é possível controlar quando e como vamos capturar ou exibir uma propriedade tanto na requisição quanto na resposta, por exemplo:

```tsx
import { Exclude, Expose, Transform } from 'class-transformer';
import { IsNotEmpty, Length, Validate } from 'class-validator';
import { IdadeValida } from '../validator-idade';

export class CreateUserDto {
  @IsNotEmpty({ message: 'Nome não pode ser vazio' })
  @Length(3, 10, { message: 'Nome precisa ter entre 3 e 10 caracteres' })
  @Transform(({ value }) => value.toLowerCase())
  @Expose({ name: 'nome_completo' })
  nome: string;

  @IsNotEmpty()
  idade: number;

  @Exclude()
  id: number;
}

```

Desta forma, a propriedade que será considerada como ‘nome’ no corpo da requisição terá que ser enviada como ‘nome\_completo’, e ao retornar esse dto, veja que a propriedade id está com o decorator `@Exclude`, portanto, ela será ignorada e a propriedade nome também será exibida como ‘nome\_completo´.

Por fim, também é necessário mais uma configuração no arquivo `main.ts` para que a serialização seja efetuada de forma global na aplicação:

```tsx
import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common';
import { NestFactory, Reflector } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  //uso global de interceptor, e a serialização dos dados nas requisições.
  app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
  app.useGlobalPipes(new ValidationPipe({ transform: true })); 
  await app.listen(3000);
}
bootstrap();

```

Aqui vimos o básico do class-validator e class-transformer, porém são recursos que possuem inúmeras funcionalidades, algumas delas abordamos no artigo [validação e serialização no NestJS](https://www.treinaweb.com.br/blog/validacao-e-serializacao-no-nestjs-class-validator-e-class-transformer).

[  ![Node.js - Fundamentos](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/node-js.svg)   Curso Node.js - Fundamentos Conhecer o curso ](https://www.treinaweb.com.br/curso/nodejs-fundamentos)

## NestJS com template engine handlebars

Podemos utilizar [templates engines](https://www.treinaweb.com.br/blog/o-que-e-template-engine "templates engines") para criar aplicações full stack com o NestJS, uma delas é o [Handlebars](https://handlebarsjs.com/guide/ "Handlebars"). Agora veremos como utiliza-la.

Primeiramente vamos instalar o Handlebars, com o comando:

```bash
npm i hbs

```

É necessário configurar a utilização do template engine e também apontar em qual diretório estarão as views, que serão os arquivos referentes as nossas páginas. Essa configuração deve ser feita no arquivo `main.ts`:

```tsx
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.useStaticAssets(join(__dirname, '..', 'public')); //arquivos públicos
  app.setBaseViewsDir(join(__dirname, '..', 'views')); //views
  app.setViewEngine('hbs');

  await app.listen(3000);
}
bootstrap();

```

### Criando e renderizando uma view

Neste momento podemos começar a desenvolver nossas views, vamos criar um diretório chamado views na raiz do projeto e criar um arquivo chamado index.hbs:

```html

    Uma View com Handlebars

    NestJS com Handlebars!

```

Precisamos criar uma rota para a view, e também utilizar o decorator `@Render()`, desta forma quando houver uma requisição para esta rota será renderizado a view respectiva:

```tsx
import { Controller, Get, Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index')
  index() {
    //
  }
}

```

Ao executar e acessar a aplicação, teremos o seguinte resultado:

![Tela com o texto nestjs com handlebars sendo exibido](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/04/Captura-de-Tela-2023-04-03-a%CC%80s-14.56.27.png)

Para ver outros recursos do Handlebars você pode acessar o [artigo NestJS com template engine Handlebars](https://www.treinaweb.com.br/blog/nestjs-com-template-engine-handlebars).

[  ![Nest.js - Templates com Handlebars](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/nest-js.svg)   Curso Nest.js - Templates com Handlebars Conhecer o curso ](https://www.treinaweb.com.br/curso/nestjs-templates-com-handlebars)

## Como enviar emails com NestJS e Nodemailer

Primeiramente, crie um novo projeto com o NestCLI, conforme descrito no ínicio deste guia.

Agora, podemos utilizar o módulo Nodemailer para nos auxiliar no envio de emails utilizando o NestJS, para isto vamos primeiro fazer a sua instalação executando os comandos:

```tsx
npm i @nestjs-modules/mailer nodemailer
npm i --save-dev @types/nodemailer

```

Ótimo, agora precisamos configurar um serviço de envio de emails, neste exemplo vamos utilizar o [mailgun](https://www.mailgun.com/), onde podemos criar uma conta gratuita para testes. Lembrando que NÃO é necessario colocar método de pagamento no cadastro.

A conta de teste irá permetir que enviemos emails para endereços cadastrados, portanto, cadastre um email que será utilizado para essa finalidade. O mailgun irá fornecer um usuário e senha para a utilização de envio de emails via SMTP, guarde essas informações.

O próximo passo será configurar o mailgun em nossa aplicação, para isto, vamos importar o MailModule no arquivo `app.module.ts`:

```tsx
@Module({
  imports: [
    MailerModule.forRoot({
      transport: {
        host: 'smtp.mailgun.org', //host smtp
        secure: false, //regras de segurança do serviço smtp
        port: 587, // porta
        auth: { //dados do usuário e senha
          user: 'seu-usuario',
          pass: 'sua-senha',
        },
        ignoreTLS: true,
      },
      defaults: { // configurações que podem ser padrões
        from: '"',
      },
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

```

Criar o método `enviarEmail()` no arquivo `app.service.ts`:

```tsx
import { MailerService } from '@nestjs-modules/mailer';
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  constructor(private mailerService: MailerService) {}

  async enviarEmail(email: string, mensagem: string) {
    await this.mailerService.sendMail({
      to: email, //email de destino, lembre-se de passar o email cadastrado no mailgun
      from: 'wesley.gado@treinaweb.com.br',
      subject: 'Enviando Email com NestJS',
      html: `${mensagem}`,
    });
  }
}

```

Agora vamos criar uma view onde estará o formulário para envio de email, para isto, vamos fazer o processo do tópico acima de instalação e configuração do Handlebars e então criar a view `forms.hbs`:

```html

  Envio de Email

          Envio de emails utilizando NestJS

      Enviar Email

```

E por fim, precisamos configrar as rotas, tanto a rota GET para acessar a view referente ao formulário, quanto a rota POST que será responsável por enviar os dados do formuário para o nodemailer:

```tsx
import { Controller, Get, Post, Render, Request } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('email')
  @Render('form')
  exibirForm() { //acessar página de formulário
  //
  }

  @Post('enviar-email')
  enviarEmail(@Request() req) { //enviar dados do formulário para o nodemailer
    return this.appService.enviarEmail(
      req.body.email,
      req.body.mensagem,
    );
  }
}

```

Desta forma a aplicação será capaz de enviar emails utilizando um servidor SMTP.

Caso você queira mais detalhes sobre a criação da conta no mailgun e o passo a passo de toda a configuração, temos o artigo completo [Como enviar emails com NestJS e Nodemailer](https://www.treinaweb.com.br/blog/como-enviar-emails-com-nestjs-e-nodemailer).

[  ![Express - Desenvolvendo aplicações web](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/express.svg)   Curso Express - Desenvolvendo aplicações web Conhecer o curso ](https://www.treinaweb.com.br/curso/express-desenvolvendo-aplicacoes-web)

## Upload local de arquivos com NestJS

Nesse tópico veremos como fazer upload de arquivos localmente com NestJS, para começar, vamos criar um novo projeto e configurar um banco de dados conforme o inicio desse guia, logo em seguida vamos criar o recurso files com o seguinte comando:

```tsx
nest g res files --no-spec

```

Perfeito, agora devemos configurar a entidade files:

```tsx
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class File {
  @PrimaryGeneratedColumn('increment')
  id: number;

  @Column({ nullable: false, unique: true })
  fileName: string;

  @Column({ nullable: false })
  contentLength: number;

  @Column({ nullable: false })
  contentType: string;

  @Column({ nullable: false })
  url: string;
}

```

Desse modo vamos salvar algumas propriedades do arquivo no banco de dados, são elas:

- **id**: o número de identificação do arquivo;
- **fileName**: o nome do arquivo;
- **contentLength**: o tamanho do arquivo;
- **contentType**: o [mimetype](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Basics_of_HTTP/MIME_types) que identifica do arquivo;
- **url**: a url gerada para acessar o arquivo, caso seja necessário em uma aplicação web por exemplo.

Vamos utilizar o módulo [Multer](http://expressjs.com/en/resources/middleware/multer.html), onde podemos consultar algumas especificações na própria [documentação do NestJS](https://docs.nestjs.com/techniques/file-upload), para realizar o upload dos arquivos. Para instala-lo basta executar o comando:

```tsx
npm i -D @types/multer

```

Agora é necessário configurar o multer, onde vamos criar uma constate com essas configurações em um arquivo que tem somente essa responsabilidade, o `multer-config.ts`:

```tsx
import { diskStorage } from 'multer';
import * as path from 'path';
import { v4 as uuidv4 } from 'uuid';

const multerConfig = {
  storage: diskStorage({
    destination: './upload/files',
    filename: (req, file, cb) => {
      const fileName =
        path.parse(file.originalname).name.replace(/\s/g, '') + '-' + uuidv4();

      const extension = path.parse(file.originalname).ext;
      cb(null, `${fileName}${extension}`);
    },
  }),
};

export default multerConfig;

```

Basicamente, indicamos que o arquivo será salvo localmente, passamos o diretório do arquivo e adicionamos um nome único para o arquivo.

Devemos criar o método na camada de serviço para salvar os dados, desta forma:

```tsx
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { File } from './entities/file.entity';
import { Request } from 'express';

@Injectable()
export class FilesService {
  constructor(
    @InjectRepository(File)
    private fotoRepository: Repository,
  ) {}
  async salvarDados(file: Express.Multer.File, req: Request) {
    const arquivo = new File();
    arquivo.fileName = file.filename;
    arquivo.contentLength = file.size;
    arquivo.contentType = file.mimetype;
    arquivo.url = `${req.protocol}://${req.get('host')}/files/${file.filename}`;

    return await this.fotoRepository.save(arquivo);
  }
}

```

Agora precisamos configurar o controller, onde vamos receber o arquivo propriamente dito e os dados deste arquivo que serão salvos no banco de dados.

Portanto, vamos criar uma rota `files` que será uma rota POST responsável por enviar os dados e o arquivo para upload:

```tsx
import {
  Controller,
  Post,
  UseInterceptors,
  UploadedFile,
  Req,
} from '@nestjs/common';
import { FilesService } from './files.service';
import { FileInterceptor } from '@nestjs/platform-express';
import multerConfig from './multer-config';
import { Request } from 'express';

@Controller('files')
export class FilesController {
  constructor(private readonly filesService: FilesService) {}

  @Post()
  @UseInterceptors(FileInterceptor('arquivo', multerConfig))
  uploadArquivo(
    @UploadedFile() file: Express.Multer.File,
    @Req() req: Request,
  ) {
    return this.filesService.salvarDados(file, req);
  }
}

```

Podemos testar fazendo o upload de um arquivo utilizando o [insomnia](https://insomnia.rest/), configurando a rota POST para `http://localhost:3000/files`, lembrando que devemos selecionar o body referente a Multipart Form, colocar o nome da propriedade como ‘arquivo’ e então selecionar file para o tipo de arquivo, por último, selecionar o arquivo que será efetuado o upload.

![Selecionando arquivo para envio no formulário](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/05/selecionando-arquivo.png)

Então podemos realizar a requisição, se tudo ocorrer corretamente, vamos obter o retorno 201 created, será salvo no banco os dados os dados arquivo, e o arquivo no diretório que configuramos no multer.

Para ver mais detalhes de como realizar o upload no NestJS, e até a possibilidade de fazer upload de múltiplos arquivos, entre em nosso artigo mais aprofundado [Como realizar upload de arquivos locais no NestJS](https://www.treinaweb.com.br/blog/como-realizar-upload-de-arquivos-locais-no-nestjs).

## Upload de arquivos no S3

Agora podemos ver como realizar o upload de imagem para a AWS S3, neste cenário vamos utilizar o [Multer s3](https://github.com/anacronw/multer-s3), uma variação do Multer especifica para essa finalidade, e o [SDK da AWS](https://github.com/aws/aws-sdk-js-v3). Então, vamos executar o seguinte comando:

```tsx
npm i aws-sdk multer-s3
npm i -D @types/multer-s3

```

Perfeito, será necessario atualizarmos o arquivo `multer-config.ts`, ou podemos criar outro similar porém com as alterações abaixo:

```tsx
import * as multerS3 from 'multer-s3';
import { S3Client } from '@aws-sdk/client-s3';
import * as path from 'path';
import { v4 as uuidv4 } from 'uuid';

const s3Config = new S3Client({
  region: 'sa-east-1', //região selecionada na criação do bucket
  credentials: {
    accessKeyId: 'chave de acesso', //chave de acesso
    secretAccessKey: 'chave de acesso secreta', //chave de acesso secreta
  },
});

const multerConfig = {
  storage: multerS3({
    s3: s3Config,
    bucket: 'artigo-tw-s3',
    contentType: multerS3.AUTO_CONTENT_TYPE,
    acl: 'public-read',
    key: (req, file, cb) => {
      const fileName =
        path.parse(file.originalname).name.replace(/\s/g, '') + '-' + uuidv4();

      const extension = path.parse(file.originalname).ext;
      cb(null, `${fileName}${extension}`);
    },
  }),
};

```

Veja que neste caso temos duas cosntantes, uma com as configurações do S3, e a constante multerConfig com as alterações relacionadas a mudança do destino do arquivo, no caso a AWS S3.

Também será necessario atualizar o Controller, já que agora estamos utilizando o Multer S3:

```tsx
import {
  Controller,
  Post,
  UseInterceptors,
  UploadedFile,
  UploadedFiles,
} from '@nestjs/common';
import { FilesService } from './files.service';
import {
  FileFieldsInterceptor,
  FileInterceptor,
} from '@nestjs/platform-express';
import multerConfig from './multer-config';

@Controller('files')
export class FilesController {
  constructor(private readonly filesService: FilesService) {}

  @Post()
  @UseInterceptors(FileInterceptor('arquivo', multerConfig))
  uploadArquivo(@UploadedFile() file: Express.MulterS3.File) {
    console.log(file);
    return this.filesService.salvarDados(file);
  }
}

```

Perfeito, podemos testar utilizando o insomnia novamente, desta forma teremos os dados do arquivo salvos no banco de dados localmente, mas teremos o arquivo salvo na AWS S3.

Caso você queira realizar o upload de vários arquivos, ou não tenha familiaridade com a AWS S3, veja nosso artigo detalhado com a criação da conta no S3 e outros rescursos em [Como realizar upload no S3 com NestJS](https://www.treinaweb.com.br/blog/como-realizar-upload-no-s3-com-nestjs).

## Autenticação: Geração de Token JWT com NestJS e Passport.

Pedemos deixar nossas aplicações seguras utilizando autenticação JWT e para isto vamos utilizar a biblioteca do Passport que é recomendada pela própria documentação do NestJS, que é uma biblioteca muito utilizada no escossistema Node.js.

Primeiramente para criarmos uma aplicação novamente, vamos utilizar o passo a passo do inicio deste guia para criar um novo projeto com o NestCLI e configurar o banco de dados. Após, podemos criar um recurso `Users`, e então, criar a entidade e o DTO:

```tsx
//user.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn('increment')
  id: number;

  @Column()
  nome: string;

  @Column()
  email: string;

  @Column()
  password: string;
}

```

```tsx
//create-user.dto.ts
export class CreateUserDto {
  nome: string;
  email: string;
  password: string;
}

```

Vale salientar que em uma \[aplicação real é importante utilizar meios de criptografia de **senha**, como o bcrypt\]. (https://docs.nestjs.com/security/encryption-and-hashing).

Perfeito, agora o segundo passo é instalar o Passport:

```bash
npm install @nestjs/jwt passport-jwt @nestjs/passport passport passport-local
npm install --save-dev @types/passport-jwt @types/passport-local

```

Agora temos os pacotes necessários para a implementação do JWT. Logo em seguida vamos criar o diretório `auth` em `src`, criar um módulo em `/auth` o seus respectivos `service` e `controller`:

```bash
nest g module auth
nest g service auth
nest g controller auth

```

Com os arquivos criados, vamos configurar o `auth.service.ts`, desta forma:

```tsx
//auth.service.ts
import {
  Injectable,
  NotAcceptableException,
  UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User } from 'src/users/entities/user.entity';
import { UsersService } from 'src/users/users.service';

@Injectable()
export class AuthService {
  constructor(
    private readonly usersService: UsersService,
    private jwtService: JwtService,
  ) {}

//validar usuário
  async validarUsuario(username: string, password: string): Promise {
    const user = await this.usersService.findOneByEmail(username);
    if (!user) {
      throw new UnauthorizedException('Usuário ou Senha Inválidos');
    }
    if (user.password === password) {
      return await this.gerarToken(user);
    }
    throw new UnauthorizedException('Usuário ou Senha Inválidos');
  }

//gerar JWT Token
  async gerarToken(payload: User) {
    return {
      access_token: this.jwtService.sign(
        { email: payload.email },
        {
          secret: 'topSecret512',
          expiresIn: '50s',
        },
      ),
    };
  }
}

```

No método `gerarToken` vamos receber o usuário caso esteja tudo ok, e então utilizaremos o `jwtService.sign`, esse método faz parte do pacote do Passporte, que permite gerar tokens com diversas opções, neste caso, vamos utilizar duas propriedades:

- secret: É uma key que será utilizada para gerer o Token, o que garante a segurança do Token JWT de forma que outra aplicação não consiga gerar o mesmo Token JWT.
- expiresIn: O tempo de duração do Token, podemos selecionar um tempo para que esse token deixe de ser válido, desta forma sendo necessário gerar outro token, permitindo que não seja utilizado de forma maliciosa caso algum atacante tenha acesso a esse Token.

**Obs**: no artigo passamos a secret direto na propriedade, porém é importante que para esses dados sensíveis sejam utilizados as variáveis de ambiente.

Outro ponto que não pode passar desapercebido é que temos o método `findOnByEmail` recebendo o `username` como parâmetro, porém não temos ele em nosso `usersService`, para isto, vamos criar um novo método de busca de usuário por email no arquivo `users.service.ts`:

```tsx
//users.service.ts
//[...]
findOneByEmail(username: string) {
    return this.userRepository.findOneBy({ email: username });
  }
//[...]

```

Ótimo! O arquivo `auth.service.ts` está configurado.

A próxima etapa é criar o arquivo `local.auth.ts`, neste arquivo vamos configurar a estratégia de autenticação do Passport, ele possibilita a configuração de várias estratégias que podem ser consultadas na sua documentação e então escolhidas conforme a sua necessidade. Neste caso vamos selecionar a estratégia local e o JWT, o arquivo `local.auth.ts` ficará da seguinte forma:

```tsx
//local.auth.ts
import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super();
  }

  async validate(username: string, password: string): Promise {
    const user = await this.authService.validateUser(username, password);
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

```

Com o `auth.service` e `local.auth.ts` configurados, precisamos adicionar os imports e providers no módulo auth:

```tsx
//auth.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from 'src/users/entities/user.entity';
import { UsersService } from 'src/users/users.service';
import { AuthService } from './auth.service';
import { LocalStrategy } from './local-strategy';

@Module({
  imports: [
    TypeOrmModule.forFeature([User]),
    PassportModule,
    JwtModule,
  ],
  providers: [AuthService, UsersService, LocalStrategy],
})
export class AuthModule {}

```

No módulo basicamente vamos importar o `TypeOrmModule` pois precisamos utilizar a busca do usuário no banco, o `PassportModule` e o `JwtModule` que são os responsáveis pela autenticação. Nos providers vamos utilizar o `UsersService` e o `LocalStrategy`, que devem ser adicionados.

Neste momento precisamos configurar a rota no `auth.controller`:

```tsx
//auth.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';

@Controller()
export class AuthController {
  constructor(private authService: AuthService) {}

  @Post('auth/login')
  async login(@Body() body) {
    return this.authService.validarUsuario(body.username, body.pass);
  }
}

```

Portanto teremos a rota POST para `/auth/login`, passando o `username` e `pass` via body chamando o método `validarUsuario` do `authService` para efetuar a validação e geração do Token.

OBS COLOCAR EXEMPLO

Para mais detalhes você pode acessar o artigo [Autenticação: Geração de Token JWT com NestJS e Passport](https://www.treinaweb.com.br/blog/autenticacao-geracao-de-token-jwt-com-nestjs-e-passport).

[  ![Node.js - Templates com PUG](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/node-js.svg)   Curso Node.js - Templates com PUG Conhecer o curso ](https://www.treinaweb.com.br/curso/nodejs-templates-com-pug)

## Protegendo rotas com NestJS e Passport

Utilizando o exemplo acima, vamos dar continuidade em relação a autenticação, agora que podemos gerar tokens JWT para usuários autenticados, vamos proteger as rotas de forma que somente esses usuários possam ter o devido acesso.

Primeira rota que podemos criar é a rota de listagem de usuários, que irá retornar uma lista de todos os usuários cadastrados na aplicação.

Portanto, vamos configurar um método no service que retorne esta lista:

```tsx
@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository,
  ) {}
  create(createUserDto: CreateUserDto) {
    return this.userRepository.save(createUserDto);
  }

  findAll() {
    return {
      usuarios: [
        {
          nome: 'Paulo',
          endereco: 'av paulista',
          telefone: '1155555555',
        },
        {
          nome: 'Maria',
          endereco: 'av faria lima',
          telefone: '1155555580',
        },
        {
          nome: 'Samantha',
          endereco: 'av paulista',
          telefone: '1155555590',
        },
      ],
    };
  }

	async findOneByEmail(username: string) {
    return await this.userRepository.findOneBy({ email: username });
  }
}

```

Agora vamos criar a rota no `users.controller.ts`:

```tsx
//users.controller.ts
import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { AuthGuard } from '@nestjs/passport';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  async create(@Body() createUserDto: CreateUserDto) {
    return await this.usersService.create(createUserDto);
  }

  @Get()
  @UseGuards(AuthGuard('jwt')) // Decorator responsável pelo Guard
  listarUsuarios() {
    return this.usersService.findAll();
  }
}

```

Foi criada uma rota GET que retorna a lista de usuários, sendo necessário o uso do decorator `@UseGuards()` para aplicar os Guards responsáveis por autenticação e autorização.

É possível criar Guards específicos para diferentes necessidades, como o `AuthGuard` fornecido pelo Passport, que permite especificar a estratégia utilizada, como o JWT.

Além disso, é necessário atualizar o arquivo `local.auth.ts`, renomeando-o para `jwt-strategy.ts` e alterando o nome da classe para `JwtStrategy`, realizando algumas modificações correspondentes.

```tsx
//jwt-strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { JwtPayload } from './jwt-payload';
import { UsersService } from 'src/users/users.service';
import { User } from 'src/users/entities/user.entity';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
  constructor(private usersService: UsersService) {
    super({
      secretOrKey: 'sua-chave',
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
    });
  }
  async validate(payload: JwtPayload): Promise {
    const { email } = payload;
    const user = await this.usersService.findOneByEmail(email);
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

```

Obs.: Confira onde estava a importação do LocalStrategy para atualizar para JwtStrategy.

Após essas alterações, veja que no método validate temos o tipo JwtPayload, portanto, vamos criar uma interface que terá como propriedade email:

```tsx
//jwt-payload.ts
export interface JwtPayload {
  email: string;
}

```

Finalmente podemos testar se a rota estará protegida:

- Vamos fazer uma requisição utilizando o método POST `http://localhost:3000/auth/login` com os dados de login de um usuário, desta forma será retornado um token JWT.
- Agora vamos acessar a rota de listagem de usuários GET `http://localhost:3000/users`, para isso precisamos copiar o token e passar na requisição. No insomnia basta clicar na opção Auth, selecionar Bearer e adicionar o Token.

Desta forma iremos ter como retorno a lista de usuários, agora teste fazer esse processo sem passar o token na requisição, vamos ter como resposta um erro 401 Unauthorized.

Você pode ver sobre esse tópico mais detalhes no artigo [Autenticação: Protegendo Rotas com NestJS e Passport](https://www.treinaweb.com.br/blog/autenticacao-protegendo-rotas-com-nestjs-e-passport "Autenticação: Protegendo Rotas com NestJS e Passport").

## Refresh Token

Uma estratégia para que não seja necessário efetuar o login novamente e que evita o tráfego de dados sensíveis nas requisições é o uso de refresh tokens. Com eles o servidor substitui o token expirado por um novo token de acesso utilizando um refresh token para gerar um novo token, lembrando que esse refresh token também expira, portanto, ele deve ter uma duração maior que o token de acesso.

Agora precisamos então configurar a aplicação para gerar esse refresh token junto ao token de acesso. No méotodo `gerarToken()`, vamos adicionar a constante refresh token:

```tsx
async gerarToken(payload: User) {
    const accessToken = this.jwtService.sign(
      { email: payload.email },
      {
        secret: 'sua-chave',
        expiresIn: '30s',
      },
    );

    const refreshToken = this.jwtService.sign(
      { email: payload.email },
      {
        secret: 'sua-chave-refresh',
        expiresIn: '60s', //veja o tempo de validade maior.
      },
    );
    return { access_token: accessToken, refresh_token: refreshToken };
  }

```

Ótimo, já estamos gerando o refresh token, porém é necessario verificar a validade desse refresh token, vamos implementar esse método no `auth.service.ts`, desta maneira:

```tsx
async reautenticar(body) {
    const payload: User = await this.verificarRefrestToken(body); ////este método também será implementado abaixo
    return this.gerarToken(payload);
  }

```

Agora precisamos implementar o método `verificarRefreshToken()`:

```tsx
private async verificarRefreshToken(body) {
    const refreshToken = body.refresh_token;

    if (!refreshToken) {
      throw new NotFoundException('Usuário não encontrado');
    }

    const email = this.jwtService.decode(refreshToken)['email'];
    const usuario = await this.usersService.findOneByEmail(email);

    if (!usuario) {
      throw new NotFoundException('Usuário não encontrado');
    }

    try {
      this.jwtService.verify(refreshToken, {
        secret: 'sua-chave-refresh',
      });
      return usuario;
    } catch (err) {
      if (err.name === 'JsonWebTokenError') {
        throw new UnauthorizedException('Assinatura Inválida');
      }
      if (err.name === 'TokenExpiredError') {
        throw new UnauthorizedException('Token Expirado');
      }
      throw new UnauthorizedException(err.name);
    }
  }
}

```

Basicamente vamos verificar se o usuário existe em nossa base de dados e se o token é válido, ou seja, se a secrect key bate com a key que utilizamos para gerar o token em nossa aplicação.

E por fim, vamos criar a rota no controller que será enviado o refresh token, para, se válido, retornar um novo token:

```tsx
@Post('auth/refresh')
  reautenticar(@Body() body) {
    return this.authService.reautenticar(body);
  }

```

Se tudo estiver ocorrendo da maneira correta, ao enviar o refresh token para a rota acima, vamos obter o seguinte retorno:

![Gerando tokens a partir do refresh token](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/01/gerando-tokens-a-partir-do-refresh-token.png)

Perfeito, para se aprofundar no assunto aconselho a ler o artigo [Autenticação: Refresh Token com NestJS](https://www.treinaweb.com.br/blog/autenticacao-refresh-token-com-nestjs).

[  ![Nest.js - Fundamentos](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/nest-js.svg)   Curso Nest.js - Fundamentos Conhecer o curso ](https://www.treinaweb.com.br/curso/nestjs-fundamentos)

## Conclusão

Neste guia abordamos vários tópicos, do básico ao avançado sobre a utilização do framework NestJS. Aprendemos a criar um projeto do zero, desenvolver um CRUD, enviar emails, realizar upload de arquivos tanto localmente quanto na AWS, aplicar validações e serialização de dados e muito mais! Lembrando que para cada tópico aqui abordado há um artigo exclusivo abordando o assunto de forma mais detalhada.

Por fim, caso queira aprender mais sobre [NestJS](https://nestjs.com/) saiba que aqui na [TreinaWeb](https://treinaweb.com.br/) temos o curso [Nest.js - Fundamentos](https://www.treinaweb.com.br/curso/nestjs-fundamentos) que possui **02h07 de vídeos** e um total de **18 exercícios**. Conheça também nossos outros cursos de [TypeScript](https://www.treinaweb.com.br/busca?q=TypeScript).

Veja quais são os tópicos abordados durante o curso de Nest.js - Fundamentos:

- Conhecendo a estrutura;
- Utilizando Nest CLI
- Entendendo Rotas, Controllers e Views;;
- Conexão com banco de dados;
- Usando TypeORM;
- Template Engine.

- [ #Back-end ](https://www.treinaweb.com.br/blog/tag/back-end)
- [ #Node.js ](https://www.treinaweb.com.br/blog/tag/node-js)
- [ #NestJS ](https://www.treinaweb.com.br/blog/tag/nestjs)
- [ #guia ](https://www.treinaweb.com.br/blog/tag/guia)

Autor

 ![Wesley Gado](//secure.gravatar.com/avatar/1b770ca482a7232b1885881430a592bb?d=mm)

## Wesley Gado

 Formado em Análise e Desenvolvimento de Sistemas pelo Instituto Federal de São Paulo, atuou em projetos como desenvolvedor Front-End. Nas horas vagas grava Podcast e arrisca uns três acordes no violão. 

 [Todos os artigos](https://www.treinaweb.com.br/blog/autor/wesley-gado)  

## Continue estudando

 Transforme leitura em prática com os cursos e formações da TreinaWeb.

 [Ver cursos](https://www.treinaweb.com.br/cursos)   

  Continue lendo

## Artigos relacionados

- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/06/GUIA-CSS-400x280.jpg)  [ CSS ](https://www.treinaweb.com.br/blog/categoria/css) 

     3 anos atrás

    ##  [ Guia da linguagem CSS ](https://www.treinaweb.com.br/blog/guia-da-linguagem-css) 

     Nesse guia completo veremos como funciona e quais as formas de criar estilizações com CSS, necessário para qualquer desenvolvedor front-end

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/05/como-instalar-o-csharp-e-nosso-primeiro-exemplo-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     4 anos atrás

    ##  [ Guia da linguagem C# ](https://www.treinaweb.com.br/blog/guia-da-linguagem-csharp) 

     Nesse guia de C# você aprenderá o necessário para criar os seus primeiros softwares com a linguagem de programação C#. Acesse agora mesmo!

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/03/dicionario-programador-iniciante-400x280.png)  [ Carreira ](https://www.treinaweb.com.br/blog/categoria/carreira) 

     4 anos atrás

    ##  [ Dicionário básico para quem está iniciando na programação ](https://www.treinaweb.com.br/blog/dicionario-basico-para-quem-esta-iniciando-na-programacao) 

     Você está iniciando na programação e está perdido nos termos e siglas que você lê ou ouve falar por aí? Confira neste artigo um guia rápido para você começar a se familiarizar com esse universo da TI.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2024/01/WEB-JARS-400x280.jpg)  [ Desenvolvimento Back-end ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-back-end) 

     3 anos atrás

    ##  [ WebJars: Simplifique o gerenciamento de dependências front-end ](https://www.treinaweb.com.br/blog/webjars-simplifique-o-gerenciamento-de-dependencias-front-end) 

     Otimize seu desenvolvimento Java! Descubra como o WebJars simplifica o gerenciamento de dependências front-end. Integre com facilidade e eficiência.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/08/DEPLOY-SPRING-DIGITAL-OCEAN-400x280.jpg)  [ Java ](https://www.treinaweb.com.br/blog/categoria/java) 

     3 anos atrás

    ##  [ Deploy de uma aplicação Spring Boot na DigitalOcean ](https://www.treinaweb.com.br/blog/deploy-de-uma-aplicacao-spring-boot-na-digitalocean) 

     Aprenda nesse artigo como realizar o Deploy de uma aplicação Spring Boot em uma VPS da DigitalOcena, usando ferramentas como o Nginx.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2021/01/instalacao-do-vs-code-no-windows-linux-e-macos-400x280.png)  [ Ferramentas ](https://www.treinaweb.com.br/blog/categoria/ferramentas) 

     6 anos atrás

    ##  [ VS Code - O que é e por que você deve usar? ](https://www.treinaweb.com.br/blog/vs-code-o-que-e-e-por-que-voce-deve-usar) 

     O VS Code é um dos editores de código mais utilizados no mundo. Conheça melhor essa ferramenta e entenda o motivo de sua popularidade.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/07/TEMPLATES-GRATUITOS-LANDING-PAGES-400x280.png)  [ Marketing Digital ](https://www.treinaweb.com.br/blog/categoria/marketing-digital) 

     6 anos atrás

    ##  [ Templates gratuitos para Landing Page ](https://www.treinaweb.com.br/blog/templates-gratuitos-para-landing-page) 

     Veja neste artigo templates gratuitos para Landing Page.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2017/08/saiba-o-que-e-e-como-tirar-a-certificacao-itil-400x280.png)  [ ITIL ](https://www.treinaweb.com.br/blog/categoria/itil) 

     9 anos atrás

    ##  [ Saiba o que é e como tirar a certificação ITIL ](https://www.treinaweb.com.br/blog/saiba-o-que-e-e-como-tirar-a-certificacao-itil) 

     As empresas sempre buscam aprimorar os seus processos para a obtenção de melhores resultados. Profissionais certificados que possam ajudá-las nesse e em outros objetivos são sempre benquistos.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2019/09/25004250/5-motivos-estudar-java-400x280.png)  [ Carreira ](https://www.treinaweb.com.br/blog/categoria/carreira) 

     7 anos atrás

    ##  [ 5 motivos para estudar Java ](https://www.treinaweb.com.br/blog/5-motivos-para-estudar-java) 

     Confira neste artigo cinco motivos para você colocar o Java em seu plano de estudos.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2018/01/12140601/carreira-de-desenvolvedor-de-aplicativos-como-comecar-400x280.png)  [ Desenvolvimento Mobile ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-mobile) 

     9 anos atrás

    ##  [ Carreira de desenvolvedor de aplicativos: como começar ](https://www.treinaweb.com.br/blog/carreira-de-desenvolvedor-de-aplicativos-como-comecar) 

     Saiba como se tornar um desenvolvedor de aplicativos reconhecido pelo mercado.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2017/07/node-js-por-que-voce-deve-conhecer-essa-tecnologia-400x280.png)  [ Node ](https://www.treinaweb.com.br/blog/categoria/node-js) 

     10 anos atrás

    ##  [ Node.js: por que você deve conhecer essa tecnologia? ](https://www.treinaweb.com.br/blog/node-js-por-que-voce-deve-conhecer-essa-tecnologia) 

     Neste artigo, Bruna Goss, da Umbler, esclarece o que vem a ser o Node.js, onde a sua utilização pode ser vantajosa e quando é melhor ou não contar com ele.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/11/ARTIGO-DART-400x280.jpg)  [ Dart ](https://www.treinaweb.com.br/blog/categoria/dart) 

     4 anos atrás

    ##  [ Guia da linguagem dart ](https://www.treinaweb.com.br/blog/guia-da-linguagem-dart) 

     Nesse guia da linguagem Dart você aprenderá o necessário para criar os seus primeiros softwares com a linguagem de programação Dart.

     Ler artigo

## Um ano de acesso total para você viver de programação.

 Todos os cursos e formações da TreinaWeb numa única assinatura, com professores que atuam no mercado, suporte direto e certificados. Do primeiro `console.log` ao mercado de trabalho.

- **1 ano** de acesso a **todos os cursos**
- Cursos novos **toda semana**
- Suporte **direto com professores**
- Plano de carreira **personalizado**
- **Certificados digitais** inclusos
- **Aplicativos** para Android e iOS, com **acesso offline**

    **Garantia incondicional de satisfação** 

 Teste por 7 dias e, se não fizer sentido para você, devolvemos seu dinheiro.

### Acesso completo a todos os cursos e dezenas de Formações.

 12 meses 

  Economize R$ 840,00  54% OFF 

 de 12x R$ 129,00 por apenas

 12x  R$ 59,00

 sem juros no cartão de crédito ou R$ 599,00 à vista

  Oferta termina em  **06h 13min 50s**

- Acesso imediato e ilimitado durante 1 ano.
- Plano de carreira personalizado.
- Suporte direto com professores.
- E muito mais!

 [Matricule-se agora](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26)

     [                ](https://www.treinaweb.com.br)

 Escola online de programação, tecnologia e IA.

- [  ](https://www.facebook.com/TreinaWeb/)
- [  ](https://www.instagram.com/treinaweb/)
- [  ](https://www.youtube.com/user/TreinaWeb)
- [  ](https://twitter.com/treinaweb)
- [  ](https://www.linkedin.com/company/treinaweb)
- [  ](https://github.com/treinaweb)

## Inscreva-se em nossa newsletter

Receba lançamentos, promoções e novidades.

   Seu nome     Seu WhatsApp     Seu melhor e-mail   Inscrever-se 

## Cursos

- [ Base para Devs ](https://www.treinaweb.com.br/categoria/base-para-devs)
- [ Front-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-front-end)
- [ Back-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-back-end)
- [ Mobile ](https://www.treinaweb.com.br/categoria/desenvolvimento-mobile)
- [ Bancos de Dados ](https://www.treinaweb.com.br/categoria/bancos-de-dados)
- [ Cloud ](https://www.treinaweb.com.br/categoria/cloud-computing)
- [ IA ](https://www.treinaweb.com.br/categoria/ia)
- [ E mais ](https://www.treinaweb.com.br/categoria/e-mais)
- [ Ver todos os cursos ](https://www.treinaweb.com.br/cursos)

## Conteúdo

- [ Formações ](https://www.treinaweb.com.br/formacoes)
- [ Projetos práticos ](https://www.treinaweb.com.br/projetos-praticos)
- [ Direto ao ponto ](https://www.treinaweb.com.br/direto-ao-ponto)
- [ Planos ](https://www.treinaweb.com.br#assinatura)
- [ Depoimentos ](https://www.treinaweb.com.br#depoimentos)
- [ Comunidade ](https://www.treinaweb.com.br#comunidade)
- [ Corpo docente ](https://www.treinaweb.com.br#docente)

## A empresa

- [ Sobre a TreinaWeb ](https://www.treinaweb.com.br#sobre)
- [ Perguntas frequentes ](https://www.treinaweb.com.br#faq)
- [ Vantagens de estudar na TreinaWeb ](https://www.treinaweb.com.br/vantagens-de-estudar-na-treinaweb)
- [ Cursos para empresas ](https://www.treinaweb.com.br/empresas)
- [ Sugira um novo curso ](https://www.treinaweb.com.br/sugerir-curso)
- [ Trabalhe conosco ](https://www.treinaweb.com.br/trabalhe-conosco)
- [ Artigos ](https://www.treinaweb.com.br/blog)
- [ Desenvolvedores e agentes ](https://www.treinaweb.com.br/developers)
- [ Contato ](https://www.treinaweb.com.br/contato)
- [ Política de privacidade ](https://www.treinaweb.com.br/politica-de-privacidade)
- [ Termos de uso ](https://www.treinaweb.com.br/termos-de-uso)

## Baixe nosso aplicativo

 [   Disponível na **App Store**  ](https://apps.apple.com/us/app/treinaweb/id1322729447) [   Disponível no **Google Play**  ](https://play.google.com/store/apps/details?id=br.com.treinaweb.mobile) 

  Av. Paulista, 1765, Conj 71 e 72 · Bela Vista · São Paulo · SP · 01311-200   © 2004 – 2026 TreinaWeb Tecnologia LTDA · CNPJ 06.156.637/0001-58
