Code Monkey home page Code Monkey logo

keepcoding-node-avanzado-pra's Introduction

🛒 Nodepop

👤 Marta Vilaseca Foradada
💻 XVI Bootcamp Full Stack Web
📅 2 Junio 2024

Desarrollar el API que se ejecutará en el servidor de un servicio de venta de artículos de segunda mano llamado Nodepop.


Screenshot


📄 Documentación App

Instalación e inicialización

Clonamos el repositorio en nuestro sistema

git clone [email protected]:marta-vilaseca/keepcoding-intro-node-pra.git

📂 Cambiamos al directorio del repositorio e instalamos las dependencias necesarias:

cd keepcoding-intro-node-pra
npm install

✅ Nos aseguramos que tenemos el servidor de MongoDB instalado y ejecutándose en nuestro sistema
✅ Cargamos los anuncios por defecto con que vienen incluídos en el archivo initDB.js que se proporciona en la carpeta del proyecto.

Caution

Ejecutar y confirmar este comando provocará el borrado de todo el contenido actual de la base de datos

Note

El comando solo se ejecutará con éxito si respondemos 'si' a la pregunta que se nos formula

node initDB.js

✅ Abrimos nuestro directorio del repositorio y creamos un archivo .env donde deberemos definir nuestras variables de entorno necesarias. Podemos usar como base el archivo .env.example que se incluye en el repositorio:

MONGODB_URL=mongodb://127.0.0.1:27017/nodepop
JWT_SECRET=

Únicamente deberemos asignar una cadena de texto cualquiera a la variable JWT_SECRET. Dicha cadena se usará para generar nuestro token de autenticación y puede incluir letras, números y caracteres especiales (es buena idea utilizar un gestor de contraseñas para crearla)

Caution

Este paso es muy importante ya que sin nuestras variables de entorno nuestra aplicación no funcionará

▶️ Una vez tenemos nuestra base de datos lista y las variables de entorno definidas, ya podemos inicializar nuestra aplicación

💻 npm run dev para inicializar en modo desarrollo, en el cual:

  • nodemon irá monitorizando los cambios que se produzcan en la app y reiniciando el servidor automáticamente según sea necesario
  • podremos ver información de los errores que se puedan ir produciendo, tanto en la API como en el website

🌍 npm start para inicializar en modo producción


Guía de uso

A partir de aquí podremos :

  • acceder al website de NodePop con nuestro navegador a través de la URL http://localhost:3000/ e interactuar con él mediante distintos filtros (detallados en la sección website)
  • interactuar con el API directamente mediante API requests (detalladas en la sección API), usando el propio navegador o (en el caso de los endpoints utilizando los métodos POST, PATCH o DELETE) herramientas como Postman.

Website

🔹 Para ver el listado de anuncios completo visitaremos en nuestro navegador la ruta base del website:

http://localhost:3000/

🔹 Para ver un anuncio específico usaremos la ruta base seguida de la ID del mismo:

http://localhost:3000/:id

➜ Ejemplo: http://localhost:3000/65e07cd8a31092a089d1f0fd

Note

Las ID de los anuncios podemos obtenerlas (para poder introducirlas manualmente en nuestra URL) si interactuamos con la API y recibimos los datos de los anuncios en formato JSON. Sin embargo para facilitar las cosas, en el website para acceder a cada anuncio individual bastará con clicar sobre su título o su foto.

🔹 Para ver el listado de los distintos tags que hay en la base de datos usaremos:

http://localhost:3000/tags/

Parámetros para filtrar

🔹 Para obtener un listado de anuncios filtrados por título, de manera que el nombre o título del anuncio empiece por la :cadena de caracteres especificada:

http://localhost:3000/?nombre=:cadena

➜ Ejemplo: http://localhost:3000/?nombre=vi mostrará todos los anuncios cuyo título empiece por vi

🔹 Para obtener listado de anuncios bajo un tag determinado:

http://localhost:3000/?tags=:tag

➜ Ejemplo: http://localhost:3000/?tags=mobile mostrará todos los anuncios bajo el tag mobile

🔹 Para obtener listado de anuncios en función de su status de venta:

➜ Ejemplo: http://localhost:3000/?tipo=venta muestra los anuncios de productos en venta
➜ Ejemplo: http://localhost:3000/?tipo=busqueda muestra los anuncios de productos que alguien esté buscando

🔹 Para obtener listado de anuncios filtrado por (rango de) precio:

  • Productos cuyo precio sea n o más: /?precio=:n-
    ➜ Ejemplo: http://localhost:3000/?precio=50-
  • Productos cuyo precio sea menor a n: /?precio=-:n
    ➜ Ejemplo: http://localhost:3000/?precio=-100
  • Productos cuyo precio esté entre n y n1 /?precio=:n-:n1
    ➜ Ejemplo: http://localhost:3000/?precio=50-100
  • Productos cuyo precio sea exactamente n /?precio=:n
    ➜ Ejemplo: http://localhost:3000/?precio=150

🔹 Para aplicar paginación podemos utilizar:

  • skip para saltar hasta un elemento determinado
    ➜ Ejemplo: http://localhost:3000/?skip=2 empezará la lista desde el elemento número 3
  • limit para determinar cuantos elementos queremos ver de una vez (por página)
    ➜ Ejemplo: http://localhost:3000/?limit=5 nos mostrará solo 5 elementos de una vez (por página)

🔹 Para ordenar los resultados de acuerdo a un campo determinado. Podemos incluir más de un campo separándolos por espacios, o añadir un '-' como modificador para indicar orden descendiente.

➜ Ejemplo: http://localhost:3000/?sort=-precio ordenamos por precio DESC
➜ Ejemplo: http://localhost:3000/?sort=-precio%20nombre ordenamos por precio DESC y luego nombre ASC

🔹 Ejemplo encadenando varios parámetros:

http://localhost:3000/?tags=lifestyle&limit=12&precio=100-&sort=-precio%20nombre

API

🔶 Autenticación

Novedad v2 ➡ Los endpoints de la API están ahora protegidos, así que es necesario identificarse como usuario registrado para obtener un JSON Web Token antes de realizar cualquier acción.

Desde Postman o equivalente, crearemos una POST request apuntando a http://localhost:3000/api/authenticate

A través del apartado Body > x-www-form-urlencoded enviaremos la información para autenticarnos con nuestra info de usuario, por ejemplo si utilizamos el usuario por defecto:

Key Value
email [email protected]
password 1234

La respuesta a esta request nos proporcionará un token en el siguiente formato:

{
    "tokenJWT": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NjVjNGEyYWUwZWE2NDgzNmM0M2IwMjQiLCJpYXQiOjE3MTczMzA2OTQsImV4cCI6MTcxNzMzNzg5NH0.ozPhk_OdYQi3JVkinHreHTGVqE4dv3zQhH8RcIEwLxM"
}

Dicho token será válido durante dos horas (pasado ese tiempo será necesario repetir este proceso para obtener otro). Deberemos utilizarlo siempre que necesitemos hacer cualquiera de las peticiones a la API que se detallan en los siguientes apartados.

Podremos incluir el token al hacer nuestras peticiones de cualquiera de estas tres maneras:

En el header

Screenshot

En el body

Screenshot

Como parámetro en el query

Screenshot

🔶 Para obtener anuncios (usando el método GET)

Note

Desde la v2, cualquier acción usando este endpoint necesita autenticación

A través del endpoint /api/anuncios (ruta completa http://localhost:3000/api/anuncios) podemos obtener:

  • Un listado general de todos los anuncios
  • Un listado filtrado de acuerdo a distintos criterios (nombre, status de venta, precio, tags) y que opcionalmente además podremos:
    • paginar
    • ordenar por uno o más de los campos existentes, en orden ascendente o descendente

🔸 Para obtener el listado de anuncios completo:

/api/anuncios/

🔸 Para obtener un anuncio específico usaremos la ruta base seguida de la ID del mismo:

/api/anuncios/:id

➜ Ejemplo: http://localhost:3000/api/anuncios/65e07cd8a31092a089d1f0fd

🔸 Para ver el listado de los distintos tags que hay en la base de datos usaremos:

/api/tags/

Parámetros para filtrar

🔸 Para obtener un listado de anuncios filtrados por título, de manera que el nombre o título del anuncio empiece por la :cadena de caracteres especificada:

/api/anuncios?nombre=:cadena

➜ Ejemplo: http://localhost:3000/api/anuncios?nombre=vi mostrará todos los anuncios cuyo título empiece por vi

🔸 Para obtener listado de anuncios de un tag determinado:

/api/anuncios?tags=:tag

➜ Ejemplo: http://localhost:3000/api/anuncios?tags=mobile mostrará todos los anuncios bajo el tag mobile

🔸 Para obtener listado de anuncios en función de su status de venta:

➜ Ejemplo: http://localhost:3000/api/anuncios?tipo=venta muestra los anuncios de productos en venta
➜ Ejemplo: http://localhost:3000/api/anuncios?tipo=busqueda muestra los anuncios de productos que alguien esté buscando

🔸 Para obtener listado de anuncios filtrado por (rango de) precio:

  • Productos cuyo precio sea n o más: /api/anuncios?precio=:n-
    ➜ Ejemplo: http://localhost:3000/api/anuncios?precio=50-
  • Productos cuyo precio sea menor a n: /api/anuncios?precio=-:n
    ➜ Ejemplo: http://localhost:3000/api/anuncios?precio=-100
  • Productos cuyo precio esté entre n y n1 /api/anuncios?precio=:n-:n1
    ➜ Ejemplo: http://localhost:3000/api/anuncios?precio=50-100
  • Productos cuyo precio sea exactamente n /api/anuncios?precio=:n
    ➜ Ejemplo: http://localhost:3000/api/anuncios?precio=150

🔸 Para aplicar paginación podemos utilizar:

  • skip para saltar hasta un elemento determinado
    ➜ Ejemplo: http://localhost:3000/api/anuncios?skip=2 empezará la lista desde el elemento número 3
  • limit para determinar cuantos elementos queremos ver de una vez (por página)
    ➜ Ejemplo: http://localhost:3000/api/anuncios?limit=5 nos mostrará solo 5 elementos de una vez (por página)

🔸 Para ordenar los resultados de acuerdo a un campo determinado. Podemos incluir más de un campo separándolos por espacios, o añadir un *'-'_ como modificador para indicar orden descendiente.

➜ Ejemplo: http://localhost:3000/api/anuncios?sort=-precio ordenamos por precio DESC
➜ Ejemplo: http://localhost:3000/api/anuncios?sort=-precio%20nombre ordenamos por precio DESC y luego nombre ASC

🔸 Ejemplo encadenando varios parámetros:

http://localhost:3000/api/anuncios?tags=lifestyle&limit=12&precio=100-&sort=-precio%20nombre

🔶 Para añadir un anuncio nuevo (usando el método POST)

Note

Desde la v2, cualquier acción usando este endpoint necesita autenticación

Desde Postman o equivalente, crearemos una POST request apuntando a http://localhost:3000/api/anuncios

A través del apartado Body > form-data (ya que estamos enviando una imagen es necesario usar form-data) podemos añadir un nuevo anuncio con los siguientes pares de key/value:

Key Value Requerido
nombre [Text] [String]
tipo [Text] [Booleano] true para anuncio de venta, false para anuncio de búsqueda
precio [Text] [Numérico]
tags [Text] [String] repetiremos el par key: tags / value: cadena para cada tag que queramos añadir. Tener en cuenta que solo aceptará los tags válidos
descripcion [Text] [String] opcional y solo visible en la vista de anuncio individual, podemos añadir un texto para el anuncio. Si no ponemos nada nos rellenará el espacio con un texto lorem ipsum especificado por defecto
descripcion [File] opcional. Si lo dejamos vacío nos guardará el anuncio con el placeholder por defecto no-photo.png. Formatos válidos: jpg, png, gif o webp

Tras mandarlo y si todo valida correctamente, recibiremos una respuesta en este formato:

{
  "result": {
    "nombre": "Rice cooker",
    "tipo": false,
    "precio": 110,
    "foto": "1717339819450-rice-cooker.png",
    "tags": ["home", "lifestyle"],
    "descripcion": "Prueba de descripción de producto. Puede ser tan larga como necesitemos.",
    "_id": "65e3c5a2b330409bef4afbdf",
    "__v": 0
  }
}

🔶 Para modificar un anuncio existente (usando el método PATCH)

Note

Desde la v2, cualquier acción usando este endpoint necesita autenticación

Desde Postman o equivalente, crearemos una PATCH request apuntando a http://localhost:3000/api/anuncios/:id, donde reemplazaremos id por el identificador del anuncio que queremos modificar

A través del apartado Body > form-data podemos modificar el anuncio de forma similar a como haríamos para crear uno nuevo, pero solo incluyendo los campos cuyo contenido vamos a cambiar.

Por ejemplo en caso de querer modificar el precio de un anuncio:

Key Value
precio Nuevo precio, en formato [Numérico]

Al enviar y si todo valida correctamente, recibiremos una respuesta en este formato (con el anuncio entero actualizado, en este caso con nuevo precio de 200):

{
  "result": {
    "nombre": "Rice cooker",
    "tipo": false,
    "precio": 200,
    "foto": "1717339819450-rice-cooker.png",
    "tags": ["home", "lifestyle"],
    "descripcion": "Prueba de descripción de producto. Puede ser tan larga como necesitemos.",
    "_id": "65e3c5a2b330409bef4afbdf",
    "__v": 0,
    "thumbnail": "thumb-1717339819450-rice-cooker.png" 
  }
}

🔶 Para eliminar un anuncio existente (usando el método DELETE)

Note

Desde la v2, cualquier acción usando este endpoint necesita autenticación

Desde Postman o equivalente, crearemos una DELETE request apuntando a http://localhost:3000/api/anuncios/:id, donde reemplazaremos id por el identificador del anuncio que queremos eliminar.

No tenemos que introducir más parámetros. Junto con el anuncio, se borrarán su imagen y thumbnail asociados.

Caution

No nos pedirá confirmación de ningún tipo, al enviar la petición y si la id proporcionada es correcta se borrará el anuncio automáticamente

Si no ha habido ningún error, recibiremos esta respuesta:

{
  "message": "Document successfully deleted."
}

Anexo

Tags válidos

  • collectibles
  • electronics
  • fashion
  • games
  • home
  • lifestyle
  • mobile
  • motor
  • outdoors
  • work

Formatos de imagen válidos

  • .jpg, .jpeg
  • png
  • gif
  • webp

Requisitos v1

Según especificado en el enunciado o briefing, el servicio mantiene anuncios de compra o venta de artículos y permite tanto buscar como poner filtros por varios criterios, por tanto la API a desarrollar deberá proveer los métodos necesarios para esto.

Los sistemas donde se utilizará la API utilizan bases de datos MongoDB

Además del desarrollo de la API, es necesario que el site tenga una página frontend que muestre la lista de anuncios con los filtros que correspondan, según la URL introducida.

📃 Datos de cada anuncio:

  • Nombre del artículo/anuncio
  • Si el artículo está en Venta o bien el anuncio es porque alguien está buscando ese producto
  • Precio del artículo (de venta o de cuánto está dispuesto a pagar el anunciante, en caso de estarlo buscando)
  • Foto del artículo (una sola por anuncio)
  • Tags, conteniendo siempre uno o varios de los tags válidos

✅ Operaciones que debe realizar el API:

  • Lista de anuncios
    • Posibilidad de paginación
    • Filtros por tag
    • Filtros por tipo de anuncio (venta/búsqueda)
    • Filtros por rango de precio (especificando precio min y max)
    • Filtro por nombre de artículo (que empiece por el texto buscado)
  • Lista de los tags existentes
  • Creación de anuncio

➕ Extras valorados positivamente:

  • Documentación
  • Validar nuestro código con ESLint

Requisitos v2

🔒 Autenticación con JWT

  • Implementar autenticación JWT al API (no es necesario hacerlo en el website)
    • POST /api/authenticate para hacer login y devolver un token JWT
    • GET /api/anuncios incluyendo el JWT en una cabecera o query-string hará la petición correcta (200 OK)
    • GET /api/anuncios sin token responderá con un código de status HTTP 401 y un json con info del error
    • GET /api/anuncios con un token caducado responderá con un código de status HTTP 401 y un json con info del error
  • Incluir para el API (al menos) un usuario con email [email protected] y clave 1234

🌍 Internacionalización

  • Convertir el frontend de Nodepop en multi-idioma (No es necesario internacionalizar el API)
  • Con selector de idioma donde el usuario pueda cambiar de un idioma a otro
  • Dos idiomas disponibles:
    • Español
    • Inglés

📷 Subida de imagen con tarea en background

  • El API necesita un endpoint para crear anuncios
    • POST /api/anuncios
    • Permite que el cliente del API suba una imagen y esta se guarde en el servidor
      • Cuando hagamos las peticiones GET /api/anuncios nos son devueltas las rutas a éstas imágenes y éstas funcionan
    • Cada imagen que se suba debe tener un thumbnail. Podemos hacer un microservicio que reciba trabajos (Cote, RabbitMQ) creando dichos thumbnails:
      • Elegir, instalar y probar un paquete que nos permita cambiar imágenes de tamaño en Node (Jimp)
      • Hacer que el API mande un mensaje (con Cote o con una cola de RabbitMQ) con la ruta del filesystem a la imagen
      • Crear un worker que esté suscrito
  • Como extra, se ha instalado la librería Concurrently para poder arrancar el microservicio conjuntamente con npm run dev o npm start, sin necesidad de arrancarlos por separado manualmente en otra terminal

✅ OPCIONAL: Tests con supertest

  • Como extra, aunque finalmente no implementado, también se pedía la creación de tests para la aplicación con Supertest

keepcoding-node-avanzado-pra's People

Contributors

marta-vilaseca avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.