Iniciando com Adonis JS - Criando uma REST API usando PostgreSQL
Adonis JS é um framework JavaScript muito poderoso, bastante parecido com o Laravel, que é voltado para a linguagem PHP. Ele também é baseado no conceito de MVC.
Neste artigo vamos aprender como podemos usá-lo para criar uma API de cursos, tendo como base de dados um Banco PostgreSQL.
Instalando o Adonis JS
O site oficial do Adonis é adonisjs.com. Para iniciar um projeto com esse framework, precisamos primeiro instalar a sua interface de linha de comando (CLI). Para isso, vamos executar o seguinte comando no Terminal:
npm install -g @adonisjs/cli
O npm irá fazer uso de nossa internet para baixar o Adonis de maneira global em nossa máquina.
Iniciando o projeto com Adonis
Para iniciar um novo projeto com o Adonis, iremos executar o comando adonis new, desta forma:
adonis new hcode-api-cursos --api-only
Com este comando iremos definir um nome para o projeto e definiremos que ele será apenas uma API. Assim, o Adonis trará apenas os arquivos e recursos necessários para criar uma API. Algumas pastas que são comuns em projetos onde o Adonis renderiza HTML, por exemplo, não serão incluídas, o que vai deixar nosso projeto mais leve e rápido.
Após executar este comando, uma mensagem de sucesso será retornada em nosso Terminal:
A estrutura de pasta de nosso projeto é a seguinte:
Criando primeira rota
Vamos agora criar nossa primeira rota! Para isso, vamos acessar o arquivo start/routes.js. De início, veremos a seguinte estrutura:
Iremos substituí-la por uma rota chamada “/routes”. Ela terá a seguinte estrutura:
Route.get('/courses', () => {
return { message: 'Hcode Treinamentos Courses!' }
});
Para iniciar o nosso servidor Adonis, iremos executar adonis serve --dev no Terminal. A seguinte mensagem será retornada:
Agora, se acessarmos http://127.0.0.1:3333/courses em nosso navegador, veremos o seguinte resultado:
Excelente, nossa primeira rota foi um sucesso!
Conectando Adonis ao Postgres
Vamos iniciar a configuração para conectar o Adonis ao Banco de Dados. Neste artigo, iremos usar o Banco de Dados PostgreSQL. Para poder manipulá-lo, vamos primeiro instalar o seu módulo em nosso projeto, através do npm:
npm install pg
O próximo passo é criar um novo Database no Postgres. Iremos chamá-lo de hcode-adonis.
Após isso, vamos adicionar as credenciais de nosso Banco. Podemos fazer isso no arquivo config/database.js. Contudo, o Adonis já nos oferece o arquivo .env, que possui as variáveis de ambiente de nosso projeto. Assim, iremos adicionar as credenciais neste arquivo. Iremos editar apenas as informações do Banco de Dados. Ele ficará da seguinte forma:
DB_CONNECTION=pg
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=root
DB_DATABASE=hcode-adonis
Criando tabelas do Banco de Dados
Iremos agora criar as tabelas de nosso Banco. Contudo, iremos fazer isso sem acessar o Postgres, mas por meio do Adonis. Talvez nos perguntemos: “Como assim? Como iremos criar as tabelas sem ir até o Banco de Dados?” Iremos fazer isso usando o recurso das migrations do Adonis. Elas são basicamente uma classe que definem a criação das tabelas do Banco de Dados por meio de código. Isso tem se tornando uma tendência nos últimos anos.
Para criar uma migration, iremos usar o seguinte comando:
adonis make:migration courses
Com esse comando, estamos dizendo que nossa migration se chamará courses. O Adonis irá perguntar se iremos criar uma tabela ou selecionar uma tabela com essa migration. Iremos selecionar a primeira opção:
Após a criação da migration, será retornada a seguinte mensagem:
Vamos agora definir a criação da nossa tabela de cursos acessando o arquivo courses_schema.js na pasta database/migrations. A classe que estará nesse arquivo possuirá dois métodos principais: 1 - up(), que define o que ocorre quando a migration é executada ou seja, quando a tabela é criada; e 2 - down(), que define o que ocorre quando realizamos um rollback em nossa migration. Geralmente definimos a exclusão da tabela nesse método. Note que podemos desfazer a criação de uma tabela se desejarmos, ou se algum erro ocorre. Assim, podemos dizer que as migrations são como que um “controle de versão de nosso Banco de Dados”.
Voltando ao método up(), vamos definir a criação de quatro colunas em nossa tabela: “name”, “description”, “url” e “price”. Para isso, usaremos o seguinte código:
up () {
this.create('courses', (table) => {
table.increments()
table.string('name', 64).notNullable()
table.string('description', 128).notNullable()
table.string('url', 64).notNullable()
table.decimal('price')
table.timestamps()
)
}
Com nossa migration pronta, vamos executá-la. Para isso, usaremos o comando adonis migration:run. Veremos a seguinte mensagem de sucesso em nosso Terminal:
Agora nossa tabela já estará criada em nosso Postgres. Bem simples, não acha?
Criando primeiro curso
Para realizar o cadastro de nosso primeiro curso, vamos precisar criar um Controller e um Model. O Adonis JS é baseado na arquitetura MVC. Por isso, essas classes são necessárias para o funcionamento de nossa API.
Para criar nosso Controller, vamos executar o seguinte comando:
adonis make:controller Course
Note nosso Controller vai ser criado no singular. Ao executar esse comando, o Adonis irá nos perguntar se desejamos que o Controller tenha o objetivo de realizar requisições HTTP ou então fazer parte de um canal para Websocket. Iremos selecionar a primeira opção:
Após executar esse comando, veremos a seguinte mensagem de sucesso:
A seguir, iremos criar nosso Model, que será acessado pelo Controller. Para isso, iremos executar o comando adonis make:model Course. Veremos a seguinte mensagem de sucesso em nosso Terminal:
Vamos editar o arquivo app/Controllers/Http/CourseController.js. A primeira coisa que iremos realizar é a requisição do Model de cursos. Faremos isso com o seguinte código:
const Course = use('App/Models/Course');
Agora estamos prontos para conectar nosso Controller ao Model para criar um curso. O primeiro método que iremos criar se chamará store(), e possuirá a seguinte estrutura:
async store({ request }) {
const dataToCreate = request.only(['name', 'description', 'url', 'price']);
return await Course.create(dataToCreate);
}
Explicando: Esse método define quais campos o Adonis irá manipular para a criação de um curso. Fazemos isso com o método request.only(). Esse método evita que campos indevidos sejam informados para nosso Model.
A seguir nós realizamos o return da chamada do método create(), que já está definido na classe Model Course por padrão. Esse método nos retorna uma promise. Assim, fazemos uso do recurso do await, para esperar essa promise ser resolvida. E, como usamos o await, nosso método store() precisa ser convertido em uma função assíncrona, por meio da palavra reservada async. Isso se repetirá para os outros métodos dessa classe.
A lógica de criação de nosso curso está pronta. O que precisamos agora é definir a chamada do método store(). Iremos fazer isso em nosso arquivo de rotas, adicionando uma segunda rota, agora com o método POST, desta forma:
Route.post('/courses', 'CourseController.store');
Perceba que é bem simples relacionar uma rota com um Controller. Precisamos apenas informar o nome do Controller juntamente com o nome do método.
Para testar se a rota está funcionando, vamos usar o Insomnia. Nós já ensinamos como instalar esse REST Client no artigo Usando Insomnia para testar as requisições de nossas APIs.
Vamos selecionar o teste da rota POST, informando os dados que queremos cadastrar:
Ao enviar essa rota de nossa API, vemos o seguinte resultado:
Muito bom! Nosso primeiro curso foi criado com sucesso, sem erros ?
Listando todos os cursos
Para listar os cursos por meio de nossa API, iremos novamente editar o arquivo de nosso Controller. Iremos criar um novo método, chamado list(). Ele possuirá o seguinte código:
async list() {
return await Course.all();
}
Apenas lembrando que o nome do método do Controller pode ser escolhido por nós. Podemos dar o nome que desejarmos. Contudo, o nome do método que chamamos pelo Model, no caso do código acima, o método all(), é padrão do Adonis e precisamos seguir esse padrão.
Iremos relacionar esse novo método com a URL GET que havíamos criado no início do artigo para testar se o Adonis estava funcionando. Essa rota ficará assim agora:
Route.get('/courses', 'CourseController.list');
E com isso nossa rota de listagem já estará funcionando :)
Agora, ao acessar http://127.0.0.1:3333/courses, veremos o seguinte resultado:
Listando os dados de um curso específico
Para a rota de seleção de apenas um curso, iremos criar um método chamado show(). Ele possuirá o seguinte código:
async show({ params }) {
return await Course.find(params.id);
}
Nesse método fizemos uso da variável de parâmetros passados pela requisição. Com base nessa informação podemos saber qual é o id do usuário que precisamos exibir na tela.
Iremos chamar esse método em nosso arquivo de rotas desta forma:
Route.get('/courses/:id', 'CourseController.show');
Note que nesse caso fizemos uso da expressão “:id” na rota. Essa variável é a responsável em selecionar o ID informado na rota de nossa API e informar seu valor para nosso Controller.
Ao acessar http://127.0.0.1:3333/courses/1, veremos as informações de apenas um curso específico.
Editando um Curso
Para editar um curso, iremos criar um método chamado update() em nosso Controller. Ele irá juntar o que já vimos de listagem de usuários e também de envio de dados. Seu código será o seguinte:
async update({ params, request }) {
const course = await Course.findOrFail(params.id);
const dataToUpdate = request.only(['name', 'description', 'url', 'price']);
course.merge(dataToUpdate);
await course.save();
return course;
}
Explicando: nós selecionamos os dados do usuário que queremos editar através do id informado nos parâmetros, mas fizemos uso do método findOrFail(), em vez de apenas find(). Por quê? Fizemos isso pois o método findOrFail() nos retornará um erro se não conseguir encontrar o curso, diferente do método find(), que apenas não retorna corpo na requisição.
Também fazemos uso do método merge() para mesclar as informações que foram enviadas para API com as informações já existentes do curso. Por fim, nós salvamos as alterações e retornamos os novos dados do curso para quem chamou a API.
Vamos fazer a chamada desse método em nosso arquivo de rotas, usando o método PUT:
Route.put('/courses/:id', 'CourseController.update');
Para realizar o teste, vamos alterar os campos de nome e url do curso. O formulário no Insomnia ficará conforme a imagem abaixo:
Após enviar os dados para a API, veremos o seguinte resultado:
Excelente, nosso curso foi atualizado com sucesso
Excluindo um Curso
Nossa operação final será a de excluir um curso. Para isso, iremos criar o método delete(), que possuirá o seguinte conteúdo:
async delete({ params }) {
const course = await Course.findOrFail(params.id);
await course.delete();
return {
message: 'Curso deletado!'
}
}
Note que o retorno do método será apenas uma mensagem de curso excluído com sucesso.
Nosso arquivo de rotas ficará assim:
Route.delete('/courses/:id', 'CourseController.delete');
Agora, ao acessar a URL http://127.0.0.1:3333/courses/1 com o método DELETE, veremos o seguinte resultado:
Nosso curso foi excluído ?
Conclusão
Você pode encontrar os códigos desenvolvidos neste artigo em nosso GitHub.
Se desejar, você pode conferir esse mesmo conteúdo em vídeo em nosso canal no YouTube.
Neste artigo aprendemos como criar uma API usando o Adonis JS. Perceba que usamos o PostgreSQL como Banco de Dados, mas quase não foi necessário acessá-lo. Foi preciso apenas criar o Banco e o Adonis se encarregou de todo o resto.
Esse framework é de fato uma excelente ferramenta para o desenvolvimento de aplicações Web rápidas e robustas, facilitando muito nosso trabalho como desenvolvedores. Se desejar aprimorar seus conhecimentos sobre a linguagem JavaScript, não deixe de fazer nosso Curso Completo de JavaScript.
Até o próximo artigo :)