💻Miércoles - Desarrollar aplicaciones Backend descentralizadas con Azle

¡Comenzamos a desarrollar con el CDK de Azle!

Este día aprederás a desarrollar Canisters utilizando el lenguaje de programación JavaScript utilizando Azle. Los temas que se cubrirán en este día son:

  • Tipos de ambientes

  • Desplegar de forma local una aplicación backend

  • Crear un API Rest con Express

Ambientes para desplegar Canisters

Para desplegar Canisters en IC tendremos dos opciones, despleagar en un entorno local y en Mainnet.

Durante este curso trabajaremos de forma local, aquí registraremos, construiremos y desplegaremos nuestros Canisters.

¿Qué es una API?

Una Interfaz de Programa de Aplicación (API por sus siglas en inglés), es un conjunto de reglas que deben seguir los programas para comunicarse entre sí.

Algunos ejemplos de API son:

  • SOAP

  • XML-RPC

  • API REST

¿Qué es una API REST?

REST es acrónimo de REpresentational State Transfer (transferencia de estado representacional) y este define condiciones sobre cómo se debe desarrollar una API.

Las API REST se comunican mediante solicitudes HTTP para realizar funciones de bases de datos estándar como crear, leer, actualizar y eliminar registros (también conocidas como CRUD) dentro de un recurso.

La estructura de llamada de una API REST se ve de la siguiente forma:

METHOD /path

Métodos más comunes

  • GET: Recuperar un recurso o una lista de recursos.

  • POST: Crear un nuevo recurso.

  • PUT: Actualizar un recurso existente.

  • DELETE: Eliminar un recurso.

Ejemplos de llamadas a API REST

GET /books HTTP/1.1
Host: api.example.com
POST /books HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "title": "Harry Potter y la piedra filosofal",
  "author": "J.K. Rowling"
}

¿Qué es Azle?

Azle es un CDK's (Canister Development Kit), que básicamente es una librería que nos permite desarrollar aplicaciones backend escritas en Typescript y que sean desplegables en el ecosistema de ICP.

Una de sus ventajas es que permite a desarrolladores web2 a introducirse más fácilmente al desarrollo de aplicaciones descentralizadas, y para principiantes representa utilizar un lenguaje con una muy amplia comunidad y documentación, así como librerías que facilitan mucho el desarrollo.

Tipos de desarrollo en Azle

Azle nos permite desarrollar de dos formas:

Canisters basados en Candid

import { Canister, query, update, bool } from 'azle';

export default Canister({
    create: update([], bool, () => {
        // Some code
    }),
    getAll: query([], Books, () => {
        return books;
    })
});

Canisters REST API

import { Server } from 'azle';
import express from 'express';

export default Server(() => {
    const app = express();
    
    app.post('/books', (req, res) => {
        // Some code
        res.send('Ok');
    });
    
    app.get('/books', (req, res) => {
        res.json(books);
    });
    
    return app.listen();
});

Rutas

Las rutas nos permiten definir URLs y métodos sobre los que haremos una acción específica, a continuación podrás ver ejemplos de algunas rutas con diferentes acciones.

import { Server } from 'azle';
import express from 'express';

type Book = {
    id: number,
    title: string,
    author: string
}

let books: Book[] = [{
    id: 1,
    title: "La Odisea",
    author: "Homero"
}];

export default Server(() => {
    export const app = express();
    
    /*
     * Method: POST
     * URL: /books
     */
    app.get("/books", (req, res) => {
        res.json(books);
    });

    /*
     * Method: POST
     * URL: /books
     * Body example:
     * {
     *    "id": 2,
     *    "title": "Dracula"
     * }
     */
    app.post("/books", (req, res) => {
        books = [...books, req.body]
        res.send("Ok");
    });

     /*
     * Method: PUT
     * URL: /books/2
     * Body example:
     * {
     *    "author": "Bram Stoker"
     * }
     */
    app.put("/books/:id", (req, res) => {
        const id = parseInt(req.params.id);
        const book = books.find((book) => book.id === id);

        if (!book) {
            res.status(404).send("Not found");
            return;
        }

        const updatedBook = { ...book, ...req.body };
        
        books = books.map((b) => b.id === updatedBook.id ? updatedBook : b);

        res.send("Ok");
    });

    /*
     * Method: DELETE
     * URL: /books/1
     */
    app.delete("/books/:id", (req, res) => {
        const id = parseInt(req.params.id);
        books = books.filter((book) => book.id !== id);
        res.send("Ok");
    });
    
    return app.listen();
});

Middlewares

Los Middleware son funciones intermedias entre la solicitud de un cliente y la ejecución de una ruta u otros middleware, estos se definen de la siguiente forma:

function middleware(req: Request, res: Response, next: NextFunction) {
    console.log("Hello from Middleware");
    next();
}

Y su implementación es de la siguiente forma:

app.use(middleware);

Ahora cada vez que hagamos un request a nuestros endpoints saldrá un log con el texto "Middleware"

Recursos

Actividades

  1. Crear un proyecto nuevo con azle new

  2. Modificar el código para que al llamar al endpoint POST /books valide si ya existe un libro con el id que se está intentando crear, en caso de que exista regresar un error de que ya existe dicho libro y no permita su creación

  3. Crear un Middleware que siempre que se llame a la API muestre un log con el body que se está mandando a cualquier endpoint

Recursos

Last updated