No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Adquiere por un a帽o todos los cursos, escuelas y certificados por un precio especial.

Antes: $249

Currency
$219/a帽o

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Comprar ahora

Termina en:

0D
6H
34M
23S

Probando nuestros endpoints

21/27
Recursos

Aportes 42

Preguntas 20

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Muy entendible todo. La verdad me encanta este curso hasta ahora.

Si te preguntas cu谩ntas funciones middleware puedes enviar como callback, la respuesta es: las que quieras. Esto siempre y cuando las separes con coma. Las puedes llamar si las definiste fuera, ejecutar o incluso llamar un array de funciones middlewares.
Ejemplo de la documentaci贸n Express

const cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}

const cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}

app.get('/example/d', [cb0, cb1], function (req, res, next) {
  console.log('the response will be sent by the next function ...')
  next()
}, function (req, res) {
  res.send('Hello from D!')
})

Les comparto una forma de personalizar los mensajes de la validaci贸n en el productSchema.js Ejemplo si queremos los mensajes en espa帽ol

const name = joi.string().min(3).max(15).messages({
  'string.base': `" nombre "debe ser un tipo de 'texto'`,
  'string.empty': `"nombre "no puede ser un campo vac铆o`,
  'string.min': `"nombre" debe tener una longitud m铆nima de {#limit}`,
  'string.max': `"nombre" debe tener una longitud m谩xima de {#limit}`
});

resultado

Si alguno ve este error en la consola:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

Lo puede solucionar anteponiendo un return antes de los res. Esto sucede porque tenemos varios middlewares en los que se responde al cliente, y no se corta la ejecuci贸n de los mismos luego de enviado el primer res, por eso el error.

Quedar铆a as铆, (ejemplo para boomErrorHandler):

function boomErrorHandler(err, req, res, next) {
	if (err.isBoom) {
		const { output } = err;
		return res.status(output.statusCode).json(output.payload);
	}
	next(err);
}

Me ha gustado mucho el curso, el profe explica super claro todos los conceptos y practicar ayuda mucho a entender mejor lo conceptos, he estado desarrollando lo que hacemos para productos con los usuarios.


Asi ser铆a mi Schema para los usuarios:

const Joi = require('joi');

const id = Joi.string().uuid();
const name = Joi.string().alphanum().min(3).max(15);
const lastname = Joi.string().alphanum().min(3).max(15);
const email = Joi.string().email();

const createUserSchema = Joi.object({
  name : name.required(),
  lastname : lastname.required(),
  email: email.required(),
});

const getUserSchema = Joi.object({
  id: id.required(),
});

module.exports = {createUserSchema, getUserSchema};
Y asi las ruta de usuarios:

const express = require("express");
const UserService = require("../services/userService");
const validatorHandler = require("../middlewares/validatorHandler");
const {createUserSchema, getUserSchema} = require("../schemas/userSchema");

const router = express.Router();
const service = new UserService();

router.get("/", async (req, res) =>{
  const users = await service.find();
  res.json(users);
});

router.post("/",
  validatorHandler(createUserSchema, "body"),
  async (req, res) =>{
    const body = req.body;
    const newUser = await service.create(body);
    res.status(201).json(newUser);
  }
);

router.delete("/:id", async (req, res) =>{
  const {id} = req.params;
  const answer = await service.delete(id);
  res.status(200).json(answer);
});

module.exports = router;

Consejo: pongan en las validaciones de price: .strict() ya que sino aceptar谩 strings con n煤meros como 鈥1000鈥 y eso puede generarnos problemas despu茅s.

Este curso es incre铆ble, hace la diferencia un buen profesor. Me han quedado claro conceptos que no hab铆a entendido bien en cursos anteriores.

Muy buen curso, hasta el momento he entendido todo .
El tema de los middlewares lo habia escuchado pero recien ahora lo estoy empezando a entender.

Para quien tenga dudas con el c贸digo de porque el profe. puso, en validatorHandler.js

const data = req[property]; 

Se debe a que para obtener data dentro de un objeto se hace de dos formas.

const objeto = {
    name: "victor",
    number: 123
}
console.log(objeto.number)
const objeto = {
    name: "victor",
    number: 123
}
console.log(objeto["number"])

Profe, tome este curso porque en mi emprendimiento ya era necesario crear una API.

El curso es muuuuuuuuuuy bueno, has tomado la informaci贸n relevante con clases cortas y concisas. De Verdad muchas gracias! me ha servido TODO

Sin duda uno de los mejores cursos que me he encontrado en Platzi. Gracias Platzi, Gracias Nicolas Molina eres la mera ley鈥 =)

para que no acepte precios en formato texto ejemplo 鈥減rice鈥: 鈥1000鈥 al validar hay que desactivar la opci贸n por defecto que lo convierte a int.

const {error} = schema.validate(data,{convert: false});

Si quieren validar que el name sea requerido pero si este contiene espacios en blanco, solamente es omitir el alphanum().

const name = Joi.string().min(3).max(15);

Para realizar ciertas restricciones con joi y poder requerir al menos un valor por ejemplo que para actualizar un usuario, por lo menos en el body venga un valor pueden usar la siguiente estructura:

Ahora entiendo a las personas que dicen las validaciones deben ir en el back end

Est谩 muy claro y pr谩ctico todo, genial el profe

por si les llega a pasar

puse: con una coma al final y me fall贸 la api

{
  "name": "Camisa",
}

lo puse as铆: y funcion贸 correctamente

{
  "name": "Camisa"
}

Para los que no les funcione en el update y hagan la petici贸n de que los campos son requeridos tienen que poner optional

const updateCategorySchema = Joi.object({
name : name.optional(),
image : image.optional(),
});

De la documentaci贸n de Joi:

number
Generates a schema object that matches a number data type (as well as strings that can be converted to numbers).

Por si alguien tambi茅n se percat贸 que se est谩 aceptando price como number o string.

Otra forma de aplicar middlewares es

router.use('/:id', validatorHandler(getProductSchema, "params"))

Esto aplica el middleware a la ruta 鈥/鈥 que le pasan por parametro el id

Mi soluci贸n como reemplazo del alphanum:

const name = Joi.string().pattern(/^[a-zA-Z0-9 ]+$/).min(3).max(25);

De esta forma se valida que el contenido sea n煤meros o letras tanto en may煤scula como min煤scula.

脕ma veo middleware por todos lados.

products.route.js:

const express = require('express');
const ProductsService = require('../../services/product.service');
const validatorHandler = require('../../middlewares/validator.handler');
const {
  createProductSchema,
  updateProductSchema,
  getProductSchema,
  deleteProductSchema,
} = require('../../schemas/product.schema');

const router = express.Router();
const service = new ProductsService();

router.get('/', async (req, res) => {
  const products = await service.find();
  res.status(200).json(products);
});

router.get(
  '/:id',
  validatorHandler(getProductSchema, 'params'),
  async (req, res, next) => {
    try {
      const { id } = req.params;
      const product = await service.findOne(id);
      if (product) {
        res.status(200).json(product);
      } else {
        res.status(404).json({ message: 'Product not found' });
      }
    } catch (error) {
      next(error);
    }
  }
);

router.post(
  '/',
  validatorHandler(createProductSchema, 'body'),
  async (req, res) => {
    const body = req.body;
    const newProduct = await service.create(body);
    res.status(201).json({
      message: 'created',
      data: newProduct,
    });
  }
);

router.patch(
  '/:id',
  validatorHandler(getProductSchema, 'params'),
  validatorHandler(updateProductSchema, 'body'),
  async (req, res, next) => {
    try {
      const { id } = req.params;
      const body = req.body;
      const product = await service.update(id, body);
      res.status(200).json({
        message: 'updated',
        product,
      });
    } catch (error) {
      next(error);
    }
  }
);

router.delete(
  '/:id',
  validatorHandler(getProductSchema, 'params'),
  async (req, res) => {
    const { id } = req.params;
    const rta = await service.delete(id);
    res.status(200).json({
      message: 'deleted',
      rta,
    });
  }
);

module.exports = router;


hasta ahora este curso de backend con nodejs me saco el sombrero, muy buena didactica en la ense帽anza y comprension de la logica a compraracion de react, wepack, nextjs que si tenia muchos vacios y muchos errores

Para el error en validatorHandler.js

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

Debemos agregar el next(); despu茅s del if ya que sino hay error debe continuar al siguiente middleware y aparentemente en el video donde lo contruimos no aparece. Pero, si aparece en los recursos de este video.

const boom = require('@hapi/boom');

function validatorHandler(schema, property) {
  return (req, res, next) => {
    const data = req[property];
    const { error } = schema.validate(data, { abortEarly: false });
    if (error) {
      next(boom.badRequest(error));
    }
    next(); // __IMPORTANTE
  }
}

module.exports = validatorHandler;

En el archivo

product.schema.js

Agregue .strict() para que al momento de hacer PATCH no pueda recibir, me di cuenta que 鈥減rice鈥 puede recibir numeros en una cadena de strings

{
"price": "2"
}

.

const price = Joi.number().integer().min(10).strict();

Es la segunda vez que veo el curso y ahora lo veo mucho m谩s claro todo.

la mayoria de javascript ha estado escrita con el patron de dise帽o builder pattern, es donde siempre se retorna this, y permite hacer el codigo tan hermoso como el siguiente:

const name = Joi.string().alphanum().min(3).max(10);

Para las personas que no obtengan el error deseado, pueden revisar el orden en el que se ejecutan los middlewares de forma global en su archivo (index) o en su (app), si los tienen separados

驴Por qu茅 el profesor no hace esto?:

const updateProductSchema = Joi.object({
  name,
  price,
  image
})

est谩 colocando los 鈥:鈥 y en JS eso es innecesario si la clave tiene el mismo nombre que el valor

As铆 es como defini mis esquemas de validaci贸n

As铆 es como defin铆 mi validado:

As铆 es como apliqu茅 las validaciones en el controlador/router

As铆 se ven mis resultados probados en postman

馃搼 Creo que una forma de manejar los valores a verificar es por un objeto y desestructuraci贸n, ya que permite actualizar la plantilla sin tener que repetir los valores no requeridos.

const Joi = require("joi");

//馃憞锔

//--Plantilla de producto--
const defaultProductSchema = {
  id: Joi.string().uuid(),
  name: Joi.string().alphanum().min(2).max(20),
  price: Joi.number().integer().min(100),
  image: Joi.string().uri(),
}
//-------




//todos los datos requeridos (id no generado por el cliente si no por la API)
const createProductSchema = Joi.object({
  name: defaultProductSchema.name.required(),
  price: defaultProductSchema.price.required(),
  image: defaultProductSchema.image.required(),
})

//solo verificacion de ID en params
const findProductSchema = Joi.object({
  id: defaultProductSchema.id.required()
})

/*ID requerido pero sin embargo verifica todas las propiedades para verificar
cualquier cambio en cualquier propiedad*/
const updatedProductSchema = Joi.object({
  ...defaultProductSchema,
  id: defaultProductSchema.id.required()
})

const deleteProductSchema = Joi.object({
  id: defaultProductSchema.id.required()
})


module.exports = { createProductSchema, findProductSchema, updatedProductSchema, deleteProductSchema };

Este curso es genial

Connect validation middleware (Joi schema) with router

He implementado el validador en Typescript de la siguiente manera:

//validator.handler.ts

import { Request, Response } from 'express';
import boom from '@hapi/boom';
import Joi from "joi";


/** Joi validator middleware */
export function validatorHandler(schema: Joi.Schema, property: string) {

  return (req: Request, res: Response, next: (arg0?: Error) => void) => {
    const data = (<any>req)[property];
    const { error } = schema.validate(data);
    if(error) {
      next(boom.badRequest(error.message));
    }
    next();
  }

}


A las rutas les pasamos los validadores que deseamos antes de que entre a la l贸gica del producto en si. En el caso de post, tenemos un validador que importamos del schema, y un body (que es de donde sacaremos la informaci贸n para validar). Nuestro validador es para crear un producto. Entonces tenemos: validadorHandler( tipoDeValidador, 鈥榙ondeLoSacamos鈥). Luego continua la l贸gica.
Products.js

router.post('/',
  validatorHandler(createProductSchema, 'body'),
  async (req, res) => {
    const body = req.body;
    const newProduct = await service.create(body);
    res.status(201).json(newProduct);
});

En caso del patch tenemos 2 parametros y requerimos 2 validadores. Nuestro primer validador es de obtener el par谩metro (ya que no requerimos realizar cambios a todo el body de nuestro producto, esa es la caracter铆stica de patch). Y por otro lado, para realizar cambios en esos parametros (que ser谩n inscriptos en el body)

router.patch('/:id',
  validatorHandler(getProductSchema, 'params'),
  validatorHandler(uptdateProductSchema, 'body'),
  async (req, res) => {
    try {
      const { id } = req.params;
      const body = req.body;
      const product = await service.update(id, body)
      res.json(product);
    } catch (error) {
      res.status(404).json({
        message: error.message
      })
    }
});

Validator.handler.js

function validatorHandler (schema, property){
  return (req, res, next) => {
    const data = req[property];

la propiedad 鈥榓bortEarly: false鈥 nos permite determinar si enviar el mensaje de error al primer error que encontremos. Por default es verdadero.

    const { error } = schema.validate(data, { abortEarly: false });
    if (error){
      next(boom.badRequest(error));
    }
    next();
  }
}

Muy bien, ya puedo validar los datos!

Excelente el curso, todo muy claro y entendible.

Ahora si me quedo clar铆simo como funciona el middleware, que bien que explica, cada detalle

Un curso incre铆ble. Estoy entendiendo todo a detalle.

la verdad excelente, boom y joi de maravilla conjunto los middlewares es una hermosura utilizarlo 馃槃

Si quieren realizar validaciones mas complejas que las que trae Joi por defecto pueden usar regex, yo lo us茅 de la siguiente forma:

const Joi = require('joi');

const id = Joi.string().uuid();
const email = Joi.string().email();
const firstName = Joi
  .string()
  .min(2)
  .max(50)
  .regex(/^\w+(?:\s+\w+)*$/)
  .messages({
    "string.pattern.base": "First Name accepts alphabetic characters, numbers and spaces"
  });
const lastName = Joi
  .string()
  .min(2)
  .max(50)
  .regex(/^\w+(?:\s+\w+)*$/)
  .messages({
    "string.pattern.base": "Last Name accepts alphabetic characters, numbers and spaces"
  });
const photo = Joi.string().uri();

const getUserSchema = Joi.object({
  id: id.required()
});

const createUserSchema = Joi.object({
  email: email.required(),
  firstName: firstName.required(),
  lastName: lastName.required(),
  photo: photo
});

const updateUserSchema = Joi.object({
  firstName: firstName,
  lastName: lastName,
  photo: photo
});

module.exports = { getUserSchema, createUserSchema, updateUserSchema };