Adonis JS es un framework JavaScript muy poderoso, bastante similar a Laravel, que está orientado al lenguaje PHP. También se basa en el concepto de MVC.
En este artículo aprenderemos cómo podemos usarlo para crear una API de cursos, teniendo como base de datos una base de datos PostgreSQL.
Instalando Adonis JS
El sitio oficial de Adonis es adonisjs.com. Para iniciar un proyecto con este framework, primero necesitamos instalar su interfaz de línea de comando (CLI). Para ello, ejecutaremos el siguiente comando en el Terminal:
npm install -g @adonisjs/cli
npm utilizará nuestra conexión a internet para descargar Adonis de manera global en nuestra máquina.
Iniciando el proyecto con Adonis
Para iniciar un nuevo proyecto con Adonis, ejecutaremos el comando adonis new, de esta manera:
adonis new hcode-api-cursos --api-only
Con este comando definiremos un nombre para el proyecto y estableceremos que será solo una API. Así, Adonis traerá solo los archivos y recursos necesarios para crear una API. Algunas carpetas que son comunes en proyectos donde Adonis renderiza HTML, por ejemplo, no serán incluidas, lo que hará que nuestro proyecto sea más ligero y rápido.
Después de ejecutar este comando, se mostrará un mensaje de éxito en nuestro Terminal:
La estructura de carpetas de nuestro proyecto es la siguiente:
Creando la primera ruta
Ahora vamos a crear nuestra primera ruta. Para ello, vamos a acceder al archivo start/routes.js. Al principio, veremos la siguiente estructura:
La sustituiremos por una ruta llamada “/routes”. Tendrá la siguiente estructura:
Route.get('/courses', () => {
return { message: 'Hcode Treinamentos Courses!' }
});
Para iniciar nuestro servidor Adonis, ejecutaremos adonis serve --dev en el Terminal. Se devolverá el siguiente mensaje:
Ahora, si accedemos a http://127.0.0.1:3333/courses en nuestro navegador, veremos el siguiente resultado:
¡Excelente, nuestra primera ruta fue un éxito!
Conectando Adonis a Postgres
Vamos a iniciar la configuración para conectar Adonis a la base de datos. En este artículo, utilizaremos la base de datos PostgreSQL. Para poder manipularla, primero vamos a instalar su módulo en nuestro proyecto, a través de npm:
npm install pg
El siguiente paso es crear una nueva base de datos en Postgres. La llamaremos hcode-adonis.
Después de eso, vamos a agregar las credenciales de nuestra base de datos. Podemos hacer esto en el archivo config/database.js. Sin embargo, Adonis ya nos ofrece el archivo .env, que contiene las variables de entorno de nuestro proyecto. Así, agregaremos las credenciales en este archivo. Solo editaremos la información de la base de datos. Quedará de la siguiente forma:
DB_CONNECTION=pg
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=root
DB_DATABASE=hcode-adonis
Creando tablas de la base de datos
Ahora vamos a crear las tablas de nuestra base de datos. Sin embargo, haremos esto sin acceder a Postgres, sino a través de Adonis. Tal vez nos preguntemos: “¿Cómo así? ¿Cómo vamos a crear las tablas sin ir a la base de datos?” Haremos esto utilizando el recurso de las migraciones de Adonis. Son básicamente una clase que define la creación de las tablas de la base de datos a través de código. Esto se ha convertido en una tendencia en los últimos años.
Para crear una migración, utilizaremos el siguiente comando:
adonis make:migration courses
Con este comando, estamos diciendo que nuestra migración se llamará courses. Adonis nos preguntará si queremos crear una tabla o seleccionar una tabla con esta migración. Seleccionaremos la primera opción:
Después de crear la migración, se devolverá el siguiente mensaje:
Ahora vamos a definir la creación de nuestra tabla de cursos accediendo al archivo courses_schema.js en la carpeta database/migrations. La clase que estará en este archivo tendrá dos métodos principales: 1 - up(), que define lo que ocurre cuando se ejecuta la migración, es decir, cuando se crea la tabla; y 2 - down(), que define lo que sucede cuando realizamos un rollback en nuestra migración. Generalmente definimos la eliminación de la tabla en este método. Tenga en cuenta que podemos deshacer la creación de una tabla si lo deseamos, o si ocurre algún error. Así, podemos decir que las migraciones son como un “control de versión de nuestra base de datos”.
Volviendo al método up(), definiremos la creación de cuatro columnas en nuestra tabla: “name”, “description”, “url” y “price”. Para ello, utilizaremos el siguiente 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()
)
}
Con nuestra migración lista, vamos a ejecutarla. Para ello, utilizaremos el comando adonis migration:run. Veremos el siguiente mensaje de éxito en nuestro Terminal:
Ahora nuestra tabla estará creada en nuestro Postgres. Muy simple, ¿no crees?
Creando el primer curso
Para realizar el registro de nuestro primer curso, vamos a necesitar crear un Controller y un Model. Adonis JS se basa en la arquitectura MVC. Por eso, estas clases son necesarias para el funcionamiento de nuestra API.
Para crear nuestro Controller, ejecutaremos el siguiente comando:
adonis make:controller Course
Nota que nuestro Controller será creado en singular. Al ejecutar este comando, Adonis nos preguntará si deseamos que el Controller tenga el objetivo de realizar solicitudes HTTP o formar parte de un canal para Websocket. Seleccionaremos la primera opción:
Después de ejecutar este comando, veremos el siguiente mensaje de éxito:
A continuación, vamos a crear nuestro Model, que será accesible desde el Controller. Para ello, ejecutaremos el comando adonis make:model Course. Veremos el siguiente mensaje de éxito en nuestro Terminal:
Vamos a editar el archivo app/Controllers/Http/CourseController.js. Lo primero que haremos es solicitar el Model de cursos. Haremos esto con el siguiente código:
const Course = use('App/Models/Course');
Ahora estamos listos para conectar nuestro Controller al Model para crear un curso. El primer método que vamos a crear se llamará store(), y tendrá la siguiente estructura:
async store({ request }) {
const dataToCreate = request.only(['name', 'description', 'url', 'price']);
return await Course.create(dataToCreate);
}
Explicando: Este método define qué campos Adonis manipulará para la creación de un curso. Hacemos esto con el método request.only(). Este método evita que campos indebidos se informen a nuestro Model.
A continuación, realizamos el return de la llamada al método create(), que ya está definido en la clase Model Course por defecto. Este método nos retorna una promesa. Así, utilizamos el recurso del await, para esperar que esta promesa sea resuelta. Y, como usamos el await, nuestro método store() necesita ser convertido en una función asíncrona, mediante la palabra reservada async. Esto se repetirá para los otros métodos de esta clase.
La lógica de creación de nuestro curso está lista. Lo que necesitamos ahora es definir la llamada al método store(). Haremos esto en nuestro archivo de rutas, agregando una segunda ruta, ahora con el método POST, de esta manera:
Route.post('/courses', 'CourseController.store');
Ten en cuenta que es muy simple relacionar una ruta con un Controller. Solo necesitamos informar el nombre del Controller junto con el nombre del método.
Para probar si la ruta está funcionando, utilizaremos Insomnia. Ya hemos enseñado cómo instalar este cliente REST en el artículo Usando Insomnia para probar las solicitudes de nuestras APIs.
Vamos a seleccionar la prueba de la ruta POST, informando los datos que queremos registrar:
Al enviar esta ruta de nuestra API, vemos el siguiente resultado:
¡Muy bien! Nuestro primer curso fue creado con éxito, sin errores ?
Listando todos los cursos
Para listar los cursos a través de nuestra API, nuevamente vamos a editar el archivo de nuestro Controller. Vamos a crear un nuevo método, llamado list(). Tendrá el siguiente código:
async list() {
return await Course.all();
}
Solo recordando que el nombre del método del Controller puede ser elegido por nosotros. Podemos darle el nombre que deseemos. Sin embargo, el nombre del método que llamamos desde el Model, en el caso del código anterior, el método all(), es estándar de Adonis y necesitamos seguir ese estándar.
Vamos a relacionar este nuevo método con la URL GET que habíamos creado al inicio del artículo para probar si Adonis estaba funcionando. Esta ruta quedará así ahora:
Route.get('/courses', 'CourseController.list');
Y con eso, nuestra ruta de listado ya estará funcionando :)
Ahora, al acceder a http://127.0.0.1:3333/courses, veremos el siguiente resultado:
Listando los datos de un curso específico
Para la ruta de selección de solo un curso, vamos a crear un método llamado show(). Tendrá el siguiente código:
async show({ params }) {
return await Course.find(params.id);
}
En este método hicimos uso de la variable de parámetros pasados por la solicitud. Con base en esta información podemos saber cuál es el id del usuario que necesitamos mostrar en pantalla.
Vamos a llamar a este método en nuestro archivo de rutas de esta forma:
Route.get('/courses/:id', 'CourseController.show');
Ten en cuenta que, en este caso, hicimos uso de la expresión “:id” en la ruta. Esta variable es la responsable de seleccionar el ID informado en la ruta de nuestra API e informar su valor a nuestro Controller.
Al acceder a http://127.0.0.1:3333/courses/1, veremos la información de solo un curso específico.
Editando un Curso
Para editar un curso, vamos a crear un método llamado update() en nuestro Controller. Este combinará lo que ya hemos visto sobre la lista de usuarios y el envío de datos. Su código será el siguiente:
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: seleccionamos los datos del usuario que queremos editar a través del id informado en los parámetros, pero hicimos uso del método findOrFail(), en lugar de solo find(). ¿Por qué? Hicimos esto porque el método findOrFail() nos devolverá un error si no puede encontrar el curso, a diferencia del método find(), que simplemente no retorna cuerpo en la solicitud.
También hacemos uso del método merge() para combinar la información que fue enviada a la API con la información ya existente del curso. Por último, guardamos los cambios y devolvemos los nuevos datos del curso a quien llamó la API.
Haremos la llamada a este método en nuestro archivo de rutas, utilizando el método PUT:
Route.put('/courses/:id', 'CourseController.update');
Para realizar la prueba, vamos a modificar los campos de nombre y url del curso. El formulario en Insomnia quedará como en la imagen a continuación:
Después de enviar los datos a la API, veremos el siguiente resultado:
Excelente, nuestro curso fue actualizado con éxito
Eliminando un Curso
Nuestra operación final será eliminar un curso. Para ello, vamos a crear el método delete(), que tendrá el siguiente contenido:
async delete({ params }) {
const course = await Course.findOrFail(params.id);
await course.delete();
return {
message: 'Curso eliminado!'
}
}
Ten en cuenta que el retorno del método será solo un mensaje de curso eliminado con éxito.
Nuestro archivo de rutas quedará así:
Route.delete('/courses/:id', 'CourseController.delete');
Ahora, al acceder a la URL http://127.0.0.1:3333/courses/1 con el método DELETE, veremos el siguiente resultado:
¿Nuestro curso fue eliminado?
Conclusión
Puede encontrar los códigos desarrollados en este artículo en nuestro GitHub.
Si lo desea, puede consultar este mismo contenido en video en nuestro canal de YouTube.
En este artículo aprendimos cómo crear una API usando Adonis JS. Observe que usamos PostgreSQL como base de datos, pero casi no fue necesario acceder a ella. Solo fue necesario crear la base de datos y Adonis se encargó de todo lo demás.
Este framework es de hecho una excelente herramienta para el desarrollo de aplicaciones web rápidas y robustas, facilitando mucho nuestro trabajo como desarrolladores. Si desea mejorar sus conocimientos sobre el lenguaje JavaScript, no deje de hacer nuestro Curso Completo de JavaScript.
Hasta el próximo artículo :)