← Node & Express

Coding challenge

an endpoint that filters and paginates an array based on the query params.

Challenge: an endpoint that filters and paginates an array based on the query params.
It must support ?search= (filters by text) and ?limit= (limits how many it returns).

Expected input / output:
  GET /productos                 -> 200 with all products
  GET /productos?search=cafe     -> 200 only those whose name contains "cafe"
  GET /productos?limit=2         -> 200 with the first 2
  GET /productos?search=t&limit=1-> 200 filters by "t" and then returns 1

How to test it:
  1. npm install
  2. node 06-retos-codigo/query-filter.js
  3. curl "http://localhost:3000/productos?search=cafe&limit=1"
Show solution
// Reto: un endpoint que filtra y pagina un array segun los query params.
// Debe soportar ?search= (filtra por texto) y ?limit= (limita cuantos devuelve).
//
// Entrada / salida esperada:
//   GET /productos                 -> 200 con todos los productos
//   GET /productos?search=cafe     -> 200 solo los que contienen "cafe" en el nombre
//   GET /productos?limit=2         -> 200 con los primeros 2
//   GET /productos?search=t&limit=1-> 200 filtra por "t" y luego devuelve 1
//
// Como probarlo:
//   1. npm install
//   2. node 06-retos-codigo/query-filter.js
//   3. curl "http://localhost:3000/productos?search=cafe&limit=1"

const express = require("express");
const app = express();
const PORT = process.env.PORT || 3000;

// Datos de ejemplo en memoria.
const productos = [
  { id: 1, nombre: "Cafe molido" },
  { id: 2, nombre: "Cafe en grano" },
  { id: 3, nombre: "Te verde" },
  { id: 4, nombre: "Chocolate" },
];

app.get("/productos", (req, res) => {
  // req.query contiene los parametros que vienen despues del "?" en la URL.
  // OJO: siempre llegan como strings (o undefined si no vienen).
  const { search, limit } = req.query;

  let resultado = productos;

  // Filtramos por texto si viene search. Comparamos en minusculas para
  // que la busqueda no distinga mayusculas de minusculas.
  if (search) {
    const termino = String(search).toLowerCase();
    resultado = resultado.filter((p) => p.nombre.toLowerCase().includes(termino));
  }

  // Paginamos con limit si viene y es un numero valido y positivo.
  // Convertimos con Number porque el query llega como string.
  if (limit !== undefined) {
    const n = Number(limit);
    if (!Number.isInteger(n) || n < 0) {
      // Si el limit es invalido, respondemos 400 en vez de comportarnos raro.
      return res.status(400).json({ error: "'limit' debe ser un entero >= 0" });
    }
    resultado = resultado.slice(0, n);
  }

  // Devolvemos el total y los datos: util para que el cliente sepa cuantos hay.
  res.status(200).json({ total: resultado.length, datos: resultado });
});

app.listen(PORT, () => {
  console.log(`Servidor de filtrado en http://localhost:${PORT}`);
});

module.exports = app;