Advanced Backend PArt I: Home

Inicio Ultima Actualización: 04/09/2024

Proyecto final de la primera parte del curso avanzado de backend en coderhouse.

Acerca de

El proyecto se estructuro de forma que pudiera mostrar una modularidad fácilmente escalable a un proyecto que solo funcione desde el server side, por ahora hay secciones del proyecto que a manera ilustrativa funcionan como una especia de frontend y tienen como nombre static como palabra clave en la nomenclatura de archivos, las rutas de renderizado y los controladores especialmente elaborados para demostración, todo esto con el objetivo de que esas partes de la aplicación puedan sustraerse de forma sencilla y rápida en posteriores iteraciones de la segunda parte del curso.

Proyecto hecho con conexión a una base de datos no-relacional basada en la arquitectura de mongoDB.

Documentación en Swagger

La aplicación cuenta con una seccion en donde se pueden verificar cada unos de los servicios asi como sus correspondientes características de consulta en la ruta /api-docs

Actualmente cuentan con solo 2 servicios agregados de productos get:api/producty get:api/product:id. Se irán agregando de manera progresiva los demás restantes.

Swagger Docs

Primeros Pasos

Esta session esta dedicada a mostrar la configuración básica del proyecto, mostrando como establecer las variables de entorno y como iniciar el proyecto.

Clonación del Repositorio

Node.js v20.16.0

Repositorio publico : https://github.com/amilcar-laniakea/ch-backend-1.git

Clonar el repositorio:

                  
                    
                      git-clone-https://github.com/amilcar-laniakea/ch-backend-final-proyect.git
                    
                  
                

Via SSH:

                  
                    
                      git@github.com:amilcar-laniakea/ch-backend-1.git
                    
                  
                

Configuración

Variables de Entorno
  • NODE_ENV: Variable que indica el tipo de deployment
  • PORT: El puerto se encuentra definido por default en el archivo principal del proyecto (app.js): 8080
  • MONGO_DB_URI: La dirección en donde se encuentra la base de datos de mongoDB
  • DATABASE_NAME: Nombre de la base de datos en mongoDB;

Instalación

Comandos de Instalación:

npm: npm install

pnpm: npm install

yarn: npm install

Inicio del Proyecto:

                  
                    
                      npm run start
                    
                  
                

Uso

Los recursos de la aplicación como condición a la persistencia requerida para el proyecto final están basado en su uso mediante una base de datos no relacional usando MongoDB, de esta forma la misma hace uso de dos colecciones para su interacción en la app teniendo la siguiente estructura:

Estructura de Productos

Estructura del Carrito de compras

Nota Importante!

En el caso anterior la variable product en el modelo de <cart> solo guarda el id del producto haciendo referencial al mismo en la colección de <products>, es un ejemplo mediante el método populate de `mongoose`, el cual se usa en la aplicación.

Respuesta de Endpoints

Los endpoints se dividen en tres archivos de rutas, las cuales manejar sus respectivos métodos de consulta: Los servicios de la APP responderán la siguiente estructura:

Ejemplo de respuesta positiva:
Ejemplo de respuesta negativa:

Nótese los atributos comunes a la respuesta: <status> indica el código de la respuesta solicitada, <data> para la información generada por la respuesta, en caso de ser una excepción su valor sera <null> y acompañada de un <message> que detalla la información de la respuesta en caso de ser necesaria, de los contrario, su valor sera <null>.

Rutas de la API

Las rutas de la API se dividen en tres archivos de rutas, las cuales manejar sus respectivos métodos de consulta: Los servicios de la APP responderán la siguiente estructura:

Rutas de Productos

  • GET: /api/productObtiene la lista de productos. Puede enviarse como parámetros opcionales `limit, page, category, status, stock, name, code y sort` todo esto con el fin de poder hacer un filtrado avanzado en el servicio y posteriormente obtener los resultados.
  • GET: /api/product/:idObtiene un producto con el id requerido por parámetro en ruta.
  • POST: /api/productCrea un producto con un id autogenerado, requiere los siguientes atributos enviados por el body (ejemplo de variables usadas en Postman para generar valores aleatorios de atributos):

                    "title":
                    "product title",
                    "description":
                    "product description",
                    "category":
                    "product category",
                    "code":
                    1,
                    "price":
                    17500,
                    "stock":
                    2
                  
                
  • PUT: /api/product/:id: Actualiza el producto requerido, pueden enviarse los mismos parámetros que en el ejemplo de crear un producto, sin embargo, son de manera opcional, y pueden editarse uno por individual por request o todos a la vez, ejemplos:

                    "title":
                    "product title",
                  
                
                  
                    "title":
                    "product title",
                    "description":
                    "product description"
                  
                
  • DELETE: /api/product/:id: borra el producto requerido

Rutas de Carros de Compras

  • GET: /api/cart: Obtiene la lista de carrito de compras creados. En este caso se usa el método populate() para hidratar el objeto producto, el cual solo esta almacenado el id y hace referencia al id en la colección de products
  • GET: /api/cart/:id: Obtiene un carrito de compras con el id requerido por parámetro en ruta.
  • POST: /api/cart: Genera un carrito de compras con un id secuencial único y lo incluye en la lista de carritos de compras, este es necesario para usar los servicios de crear y gestionar los productos del mismo.
  • POST: /api/cart/:cid/product/:pid: Este servicio tiene como principal funcion agregar productos a un carrito de compras elegido, el parámetro :cid indica el carrito objetivo a ser gestionado, como segundo parámetro :pid que representa el id del producto a agregar, este se usa junto con el parámetro por body quantity para verificar si el producto existe en la lista de productos generada y almacenada en data/products.json cuenta con la existencia de ese producto y tiene un stock suficiente para ser agregado.

    El parámetro quantity (opcional) debe ser enviado de la siguiente manera (ejemplo por Postman), en caso de no ser enviado, por default se agrega un 1 solo producto: De igual forma el parámetro isReduceQuantity (opcional) es usado para aumentar si esta en true y disminuir si esta en false la cantidad de productos del carrito, si no es enviado por default la aplicación lo toma como un true.

Nota Importante!

El parámetro isReduceQuantity es sensible y detecta la disponibilidad del stock al producto agregado, si no existe suficiente stock al momento de agregar, o al momento de disminuir mostrara un mensaje de no hay stock disponible

                  
                    "quantity":
                    2,
                    "isReduceQuantity":
                    true
                  
                
  • DELETE: /api/cart/:cid/product/:pid: Elimina un producto deseado por medio del id del carrito :cid y el id del producto :pid
  • DELETE: /api/cart/:id: Elimina un carrito de la lista de carrito de compras por medio del parámetro :id

Rutas Estáticas

Nota Importante!

El parámetro Estas rutas son para demostración de renderizado de contenido del lado der servidor para ser servido por frontend, los archivos clave de estas rutas exclusivas se encuentran en el archivo src/routes/static.router.js y sus métodos en src/controllers/static.controller.js de formas de ser abstraídas o quitadas con facilidad en el momento de no necesitarse mas como forma de hacer el proyecto mas escalable a largo plazo.

Importante!

Cada vista presenta en su mecánica un archivo JS vinculado a su lógica ubicado en la ruta src/public/js

Son las rutas usadas para renderizar del lado del servidor contenido que pueda ser visualizado y manipulado por el cliente, estas vistas permiten mostrar los productos que son devueltos anteriormente por el endpoint /api/products de forma gráfica.

Estructura de Rutas Estáticas

/views/products:

Esta muestra los productos que son consultados a la base de datos de mongoDB y los muestra sin ningún ordenamiento, de forma paginada y por default como limite de elementos un total de 10, sin embargo como se muestra en la imagen, existen una serie de filtros avanzados los cuales pueden aplicarse a la consulta como: stock, status, resultados por pagina(limit), ordenamiento (sort tipo asc y des) en relación a precio, búsqueda por nombre y por código, de igual forma en endpoint esta preparado para buscar por categorías, los cuales no se incluyeron en la demostración de este frontend (revisar colección de postman ubicada en la raíz del proyecto (postman))..

Nota Importante!

Existen 2 botones como acciones principales en cada producto renderizado, uno redirige a la vista de /views/product-detail/:pid y el otro realiza la funcionalidad de agregar un producto al carro de compra, cabe destacar que al momento de realizar esta acción se verifica si existe un id de carro de compras almacenado en localStorage de no ser asi, este consulta el servicio de generar carro de compras y posteriormente agrega el producto al mismo, en caso contrario de existir el id del carrito, solo es obtenido y usado por la funcion de agregar producto..

Descripción de la imagen

La estructura de información mostrada es la misma que la devuelta por el endpoint **GET** `api/product`

/views/product-detail/:id:

Esta vista muestra a mas detalle mas información procedente del servicio api/product/:pid que no es mostrada en la lista anteriormente descrita, de igual manera, se muestra un botón de acción ya que en esta vista es posible de igual manera agregar un producto al carro de compras obteniendo el cid de localStorage como de menciono con anterioridad.

El botón Ir Al Carrito se encuentra disponible en esta vista al igual que en la lista de productos.

Descripción de la imagen

/views/cart

Esta vista muestra los productos agregados al carrito del usuario que actualmente esta usando el equipo, esta vista verifica la existencia de un id almacenado en localStorage y desde esa verificación hace la consulta al servicio devolviendo solo el carrito correspondiente a ese id almacenado, en caso de no existir la vista mostrara un texto de no encontrado

En la vista existe por producto un botón de eliminar el cual elimina el producto elegido del carrito de compras, como dato adicional, en la vista se muestra el total de productos y precio de los mismos previamente agregados.

Como se explico con anterioridad, a modo de acotación: al momento de agregar un producto es verificado si hay un id almacenado en localStorage como nombre cart, de no ser asi es creado por el servicio correspondiente de generateCart, en caso de existir es agregado al id recogido desde localStorage.

Descripción de la imagen

Mongo DB

Existe un archivo en la carpeta src/config/db.js el cual tiene la configuración a la conexión a la base de datos:.

Conexión

HandleBars

La carpeta views contiene toda la estructura del proyecto en lo referente a la librería handlebars, tiene como carpeta principal layout en donde se encuentra el esqueleto general de la estructura html, y la carpeta partials que incluye el archivo productList que es compartido con todas las vistas estáticas.

Estructura

  1. Cada plantilla tiene sus dependencias que son invocadas por medios de CDN's
  2. Cada plantilla su archivo `.js` ubicado en la ruta `/src/public/js` que contienen la lógica necesaria para su funcionamiento
  3. La configuración de la librería `handlebars` se encuentra ubicada en el archivo `app.js`, donde están declaradas la ubicación de la carpeta `partials` detalles como extension personalizada:
                  
                    
                      const hbs = create({ extname: "hbs", partialsDir:
                      path.join(__dirname, "views", "partials")});
                    
                  
                

Postman

En la ruta/carpeta /postman se encuentra la colección de postman necesaria a importar en la aplicación de /Postman y usar los recursos de la APP, el nombre del archivo es /collection_v1.json

Estructura del Proyecto