Minha experiência com AdonisJS e como fazer seu primeiro CRUD
Tags: javascript, programming, tutorial, adonis
Published: 2024-05-26 15:16:16

## Introdução

Nesse artigo eu irei falar com minha experiência atual com o framework Adonijs um [MVC (Model-View-Controller)](https://medium.com/@habbema/nodejs-padr%C3%A3o-mvc-2f4e16b79cb8) para Node.js.

Eu tenho que admitir que já tive alguma experiência prévia com o framework, porém, nunca usei ele com 100% do seu potencial. Recentemente, recebi uma oferta de emprego que me fez aprender e usar AdonisJS de forma profissional, e fiquei surpreendido, tanto pela sua documentação, que é muito boa, quanto pelos seus padrões obrigatórios, algo que sinto muita carência nos frameworks de Node.js. Os que mais se destacam nesse aspecto são o NestJS e o AdonisJS. Isso, para mim (uma questão polêmica), é muito importante.

## Documentação e Padrões Obrigatórios
A documentação do AdonisJS é extremamente clara e detalhada, facilitando a curva de aprendizado e a resolução de problemas. Ela aborda desde conceitos básicos até funcionalidades avançadas, proporcionando uma base sólida para desenvolvedores de todos os níveis.

Os padrões obrigatórios do AdonisJS ajudam a manter o código organizado e consistente, o que é crucial para a manutenção e escalabilidade de projetos. Esse é um ponto em que muitos frameworks de Node.js falham, pois deixam muito espaço para a interpretação e implementação por parte dos desenvolvedores. Com AdonisJS, há uma estrutura bem definida que guia o desenvolvimento de forma eficiente.

## Ferramentas próprias
AdonisJS se destaca por suas ferramentas adicionais, que são bastante interessantes. Um exemplo é o [Lucid](https://lucid.adonisjs.com/docs/introduction), um ORM próprio que já vem integrado ao framework ou mesmo a sua própria CLI, uma interface de linha de comando poderosa e intuitiva, que ajuda na criação e gerenciamento de projetos, além de facilitar tarefas comuns como a criação de modelos, controladores e migrações.
Eu poderia ficar horas falando sobre essas ferramentas como Sessions, Auth configurada com um comando no CLI ( isso é incrível kkk ), Encryption, Emails e várias outras.


## Fazendo meu primeiro CRUD com AdonisJS
Depois de tantos elogios eu acho que mostrar na prática é melhor para eu te provar o como bom ele é.

Vamos criar um exemplo simples de um CRUD (Create, Read, Update, Delete) em AdonisJS V6 utilizando o Lucid ORM e a CLI do AdonisJS. Este exemplo irá envolver a criação de uma aplicação para gerenciar uma lista de tarefas.

## 1. Configuração do Projeto
Primeiro, vamos configurar um novo projeto AdonisJS:
```bash
# Instale a CLI do AdonisJS globalmente se ainda não tiver
npm install -g @adonisjs/cli

# Crie um novo projeto AdonisJS
adonis new tasks-app

# Navegue até a pasta do projeto
cd tasks-app

# Instale as dependências
npm install
```

## 2. Configuração do Banco de Dados
Configure o banco de dados no arquivo config/database.ts. Este exemplo usa SQLite para simplicidade, mas você pode usar qualquer banco de dados suportado.
```ts
// config/database.ts
const databaseConfig: DatabaseConfig = {
  connection: 'sqlite',

  connections: {
    sqlite: {
      client: 'sqlite3',
      connection: {
        filename: path.join(__dirname, '..', 'database.sqlite')
      },
      useNullAsDefault: true,
      migrations: {
        naturalSort: true,
      },
      healthCheck: false,
      debug: false,
    },
    // Outras configurações de banco de dados...
  }
}
```

## 3. Criar a Tabela de Tarefas
Vamos criar a tabela de tarefas usando migrações.

```bash
# Criar uma migração para a tabela de tarefas
adonis make:migration tasks --create=tasks
```

Edite a migração gerada em database/migrations/TIMESTAMP_tasks.ts:

```ts
import BaseSchema from '@ioc:Adonis/Lucid/Schema'

export default class Tasks extends BaseSchema {
  protected tableName = 'tasks'

  public async up () {
    this.schema.createTable(this.tableName, (table) => {
      table.increments('id')
      table.string('title').notNullable()
      table.text('description')
      table.boolean('is_completed').defaultTo(false)
      table.timestamps(true)
    })
  }

  public async down () {
    this.schema.dropTable(this.tableName)
  }
}
```
Execute a migração:

```bash
adonis migration:run
```

## 4. Criar o Modelo de Tarefa
Crie um modelo para interagir com a tabela de tarefas.

```bash
# Criar o modelo Task
adonis make:model Task
```

Edite o modelo gerado em app/Models/Task.ts:

```ts 
import { DateTime } from 'luxon'
import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm'

export default class Task extends BaseModel {
  @column({ isPrimary: true })
  public id: number

  @column()
  public title: string

  @column()
  public description: string

  @column()
  public isCompleted: boolean

  @column.dateTime({ autoCreate: true })
  public createdAt: DateTime

  @column.dateTime({ autoCreate: true, autoUpdate: true })
  public updatedAt: DateTime
}
```

## 5. Criar o Controlador de Tarefas
Crie um controlador para lidar com as operações CRUD.

```bash
# Criar o controlador TaskController
adonis make:controller Task
```

Edite o controlador gerado em app/Controllers/Http/TaskController.ts:

```ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Task from 'App/Models/Task'

export default class TaskController {
  public async index({ response }: HttpContextContract) {
    const tasks = await Task.all()
    return response.json(tasks)
  }

  public async store({ request, response }: HttpContextContract) {
    const data = request.only(['title', 'description', 'is_completed'])
    const task = await Task.create(data)
    return response.status(201).json(task)
  }

  public async show({ params, response }: HttpContextContract) {
    const task = await Task.find(params.id)
    if (!task) {
      return response.status(404).json({ message: 'Task not found' })
    }
    return response.json(task)
  }

  public async update({ params, request, response }: HttpContextContract) {
    const task = await Task.find(params.id)
    if (!task) {
      return response.status(404).json({ message: 'Task not found' })
    }

    const data = request.only(['title', 'description', 'is_completed'])
    task.merge(data)
    await task.save()

    return response.json(task)
  }

  public async destroy({ params, response }: HttpContextContract) {
    const task = await Task.find(params.id)
    if (!task) {
      return response.status(404).json({ message: 'Task not found' })
    }

    await task.delete()
    return response.status(204).json(null)
  }
}
```

## 6. Configurar as Rotas
Edite o arquivo de rotas em start/routes.ts para incluir as rotas para o CRUD de tarefas:

```ts
import Route from '@ioc:Adonis/Core/Route'

Route.get('/tasks', [TaskController.'index'])
Route.post('/tasks', [TaskController.'store'])
Route.get('/tasks/:id', [TaskController.'show'])
Route.put('/tasks/:id', [TaskController.'update'])
Route.delete('/tasks/:id', [TaskController.'destroy'])
```

## 7. Testar a Aplicação
Agora, inicie o servidor AdonisJS:

```bash
adonis serve --watch
```

Viu como é fácil e rápido? Além de você usar a CLI para fazer maioria das coisas você também mantém um padrão no seu projeto e isso é muito bom!!!

Obrigado por ler o artigo :)