Tu primera experiencia con Node.js

1

驴D贸nde aprender backend con Node.js actualizado?

2

Todo lo que aprender谩s sobre backend con Node.js

3

驴Qu茅 es Node.js?

4

驴Qu茅 es Node.js y para qu茅 sirve?

5

Diferencias entre Node.js y JavaScript

6

Resumen: Diferencias Nodejs y Javascript

7

Instalaci贸n de Node.js

8

Arquitectura orientada a eventos

9

Node.js para la web

Manejo y uso de Streams con Node.js

10

Introducci贸n a streams

11

Readable y Writable streams

12

Duplex y Transforms streams

Uso de utilidades de Node.js

13

Sistema operativo y sistema de archivos

14

Administrar directorios y archivos

15

Consola, utilidades y debugging

16

Clusters y procesos hijos

Crea tu primer proyecto en Express.js

17

驴Qu茅 es Express.js y para qu茅 sirve?

18

Creando tu primer servidor con Express.js

19

Request y Response Objects

Aprende a crear un API con REST

20

Anatom铆a de una API Restful

21

Estructura de una pel铆cula con Moockaru

22

Implementando un CRUD en Express.js

23

M茅todos idempotentes del CRUD

24

Implementando una capa de servicios

C贸mo conectarse con librer铆as externas en Express.js

25

Creaci贸n de una BD en MongoAtlas

26

Conexi贸n a MongoAtlas una instancia de MongoDB

27

Conexi贸n con Robot3T y MongoDB Compass a una BD

28

Implementaci贸n de las acciones de MongoDB

29

Conexi贸n de nuestros servicios con MongoDB

Conoce como funcionan los Middleware en Express.js

30

驴Qu茅 es un middleware? Capa de manejo de errores usando un middleware

31

Manejo de errores as铆ncronos y s铆ncronos en Express

32

Capa de validaci贸n de datos usando un middleware

33

驴Qu茅 es Joi y Boom?

34

Implementando Boom

35

Implementando Joi

36

Probar la validaci贸n de nuestros endpoints

37

Middlewares populares en Express.js

Implementa tests en Node.js

38

Creaci贸n de tests para nuestros endpoints

39

Creaci贸n de tests para nuestros servicios

40

Creaci贸n de tests para nuestras utilidades

41

Agregando un comando para coverage

42

Debugging e inspect

Despliega tu primera aplicaci贸n en Express.js

43

Considerando las mejores pr谩cticas para el despliegue

44

Variables de entorno, CORS y HTTPS

45

驴C贸mo implementar una capa de manejo de cach茅?

46

驴C贸mo contener tu aplicaci贸n en Docker?

47

Despliegue en Now

Conclusiones

48

驴Qu茅 aprendiste en este curso?

No tienes acceso a esta clase

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

Implementando una capa de servicios

24/48
Recursos

La arquitectura tradicional MVC se queda corta en aplicaciones modernas, por eso necesitamos una arquitectura diferente c贸mo la Clean Arquitecture que tiene una capa de servicios para manejar la l贸gica de negocio.

Aportes 78

Preguntas 10

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

Les dejo esta imagen que hice de la arquitectura clean

Aqu铆 mis apuntes de la arquitectura

Recordar que la diferencia entre PUT y PATH es:

Mi soluci贸n al desaf铆o:

routes/movies.js


	router.patch("/:movieId", async function(req,res,next) {
		const {movieId} = req.params;
		const {body: movie} = req;		
		try {
			const updatedMovieId = await moviesService.partialUpdateMovie({movieId,movie});

			res.status(200).json({
				data:updatedMovieId,
				message: "movie updated partially"
			});
		}
		catch(error) {
			next(error);
		}
	});

services/movies.js


	async partialUpdateMovie() {
		const updatedMovieId = await Promise.resolve(moviesMock[0].id);
		return updatedMovieId;
	}

Yo pensando que MvC era optimo, todo esta constante cambio siempre

#NuncaParesDeAprender

Si les interesa encontr茅 este link donde hablan un poco m谩s a fondo sobre la arquitectura que se va a implementar 'Clean Arquitecture鈥
https://blog.logrocket.com/the-perfect-architecture-flow-for-your-next-node-js-project/

La diferencia entre req.query y req.params, es que paramentros se utiliza cuando estan establecidos en la URL y query cuando se usa ?, el nombre query y se puede concatenar.

Buena clase, valiosa para repasarla.

De lo que mencionas al final de la clase me queda el principio de responsabilidad 煤nica de la programaci贸n.

El panadero que haga pan, el ladrillero que haga ladrillo.

En la pr谩ctica recuerdas la idea de separar responsabilidad cuando hablas de las rutas y los servicios. No sobrcargar.

No te rindas! Ya vas por la mitad del curso!

Las rutas est谩n para enviar los par谩metros y datos a los servicios, los servicios saben de la l贸gica de negocio y saben devolver respuestas.

RETO

Route:

// creamos nuestro metodo patch en el router de nuestro servidor recibiendo el id de la movie
router.patch('/:movieId', async (req, res, next) => {
    // destructuramos el parametro movieID que viene de la ruta
    const { movieId } = req.params;
    // recibimos los datos que vienen de body y colocamos un alias "dataMovie"
    const { body: dataMovie } = req;
    try{
        // llamamos al servicio patchMovie para que se encargue de la l贸gica a implementar
        const patchMovie = await movieService.patchMovie({ movieId, dataMovie });
        // enviamos la respuesta exitosa al servidor
        res.status(200).json({
            data: patchMovie,
            message: 'updated movie'
        });
    } catch(err) {
        // en caso de error lo capturamos error
        next(err);
    }
});

Servicio:

async patchMovie() {
    // revolvemos el id del registro modificado
    const updatedMovieId = await Promise.resolve(moviesMock[0].id);
    // retornamos el id
    return updatedMovieId;
}

Challenge:

/routes/

router.patch('/:movieId', async function(req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
      const movieModified = await moviesService.updateOneFieldMovie({
        movieId,
        movie
      });
      res.status(204).json({
        data: movieModified,
        message: 'movie modified'
      });
    } catch (error) {
      next(error);
    }
  }); ```





/services/


async updateOneFieldMovie() {
    const updateOneFieldMovie = await Promise.resolve(moviesMock[0].id);
    return updateOneFieldMovie;
  }

Pr谩cticamente es lo mismo, pero recordar que con patch solo es una actualizaci贸n parcial de los datos correspondientes a un recurso.

router.patch('/:movieId', async function(req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;

    try {
      const partialMovieId = await moviesServices.updatePartialMovie({
        movieId,
        movie
      });
      res
        .status(200)
        .json({ data: partialMovieId, message: 'movie updated partially' });
    } catch (err) {
      next(err);
    }
  });

Es aqu铆 donde se tendr铆a que agregar la l贸gica de un for para saber que propiedes se quieren actualizar

async updatePartialMovie() {
    const partialUpdateMovieId = await Promise.resolve(moviesMock[6].id);
    return partialUpdateMovieId;
  }

Controladores Es toda la capa del middleware y el router que se comunica con al API y reciben/envia Json.
Los controladores no llaman a otros controladores, solo llaman servicios.

*Servicios Contiene toda la logica de negocio. Los servicios pueden llamar a otros servicios o librerias.

Librerias Es la capa que adjunta librerias externas, bases de datos, bases de datos en la nube.

Exelente lectura, ahora me doy cuenta que no entendia muy bien el modelo MVC. genial!! gracias.

// patch route
router.patch('/:movieId', async (req, res, next) => {
        const { movieId } = req.params;
        const { body: movie } = req;

        try {
            const patchMovieId = await moviesService.patchMovie({ 
                movieId,
                movie
             })
            res.status(200).json({
                data: patchMovieId,
                message: 'resource updated'
            })
        } catch (err) {
            next(err);
        }
    });

// patch service 
    async patchMovie() {
        const patchMovieId = await Promise.resolve(moviesMock[0].id);
        return patchMovieId;
    }
  • en los controlladores = es toda la capa del middlewares, y del router comunicaci贸n con api donde se recibe y se env铆a JSON
  • los controlladores solo llaman servicios, pero los servicios si llaman a otros servicios y librer铆as bases de datos u otras apis
  • La unica responsabilidad de la rutas en como recibir parametros y como se los envia a los servicios

Respuesta al reto

Ruta

router.patch('/:movieId', async (req, res, next) => {
    const { movieId } = req.params
    const { body: movie } = req

    try{
        const partiallyUpdatedMovieId = await movieService.partialUpdateMovie({ movieId, movie })

        res.status(200).json({
            data: partiallyUpdatedMovieId,
            message: 'partially updated movie'
        })
    }catch(err) {
        next(err)
    }
})

M茅todo

async partialUpdateMovie() {
    const updatedMovieId = await Promise.resolve(moviesMock[0].id)
    return updatedMovieId
}

<h1>De los enlaces que dej贸 el profesor me queda lo siguiente:</h1>
  1. No hay arquitectura 煤nica, predefinidad, perfecta para una aplicaci贸n web moderna.
  2. Por lo tanto, es** tu responsabilidad no limitarte al Modelo Vista Controlador** usado en tiempos pasados (yo nunca lo he tocado) sino entender las capas, las entidades, las piezas que necesita tu aplicaci贸n para funcionar.

Para encontrar m谩s documentaci贸n pueden buscar sobre arquitectura de 3 capas, adem谩s tambi茅n es muy com煤n encontrar que la capa Librer铆as se llama Repository

Reto

dentro del services

 async patchMovie() {
    const patchedMovieId = await Promise.resolve(moviesMock[0].id);
    return patchedMovieId;
  }

dentro de routes

router.patch('/:movieId', async function (req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
      const patchedMovieId = await moviesService.patchMovie({
        movieId,
        movie,
      });

      res.status(200).json({
        data: patchedMovieId,
        message: 'movie patched',
      });
    } catch (err) {
      next(err);
    }
  });

La sentencia

return movie || [];

no la entiendo muy bien

  router.patch('/:movieId', async function (req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
      const updateDataMovie = await movieService.updateDataMovie({
        movieId,
        movie,
      });

      res.status(200).json({
        data: updateDataMovie,
        message: 'Data movie is Actualised',
      });
    } catch (error) {
      next(error);
    }
  });
  async updateDataMovie() {
    const updatedDataMovieId = await Promise.resolve(moviesMocks[0].id);
    return updatedDataMovieId;
  }

Yo uso esa estructura, de los Cursos de Node de Fernando Herrera en Udemy y otros siempre por costumbre lo he hecho as铆 pero pienso que la opci贸n que plantea el profesor es buena y ahorra carpetas. E incluso trabajando con TS se puede hacer as铆.

Como dato adicional y recordando el articulo de hace unas clases atr谩s, intente hacer un console.log a movie en el endpoint POST para comprender el alias y me mostraba undefined a煤n cuando yo le enviaba un objeto, esto es por qu茅 necesitan usar algo como: https://www.npmjs.com/package/body-parser

const bodyParser = require('body-parser')

app.use(bodyParser.json())

Con esto le dicen que esperan datos tipo JSON en el req.body

Esto lo saque de stack overflow, en donde que explica que req.params se podr铆a ver como parametros o cadenas de strings luego de despu茅s de un slash (/) y req.query son par谩metros que van despu茅s del signo de interrogaci贸n como en el ejemplo mostrado

Dada esta ruta

app.get('/hi/:param1', function(req,res){} );
and given this URL http://www.google.com/hi/there?qs1=you&qs2=tube

Tendr谩s

req.query

{
  qs1: 'you',
  qs2: 'tube'
}
req.params

{
  param1: 'there'
}

routes/movies.js

router.patch('/:movieId', async function (req, res, next) {
    const { movieId } = req.params;
    try {
      const patchMovieId = await moviesService.patchMovie({ movieId })
      res.status(200).json({
        data: patchMovieId,
        message: 'movie modified'
      });
    } catch (error) {
      next(error);
    }
  });

services/movies.js

async patchMovie() {
    const patchedMovie = await Promise.resolve(moviesMock[0].id);
    return patchedMovie || {};
  }```


Muy bueno, a pesar de que aprend铆 el CRUD en la universidad, aqu铆 aclare algunas dudas que tenia. Gracias!!

Ac谩 esta mi soluci贸n al reto

router.patch('/:id', async (request, response, next) => {
  const { id } = request.params;
  const { "body": update } = request;

  try{
    const moviePatched = await moviesService.updateMovie({ id, update });

    response.status(200).json({
      data: moviePatched,
      message: 'movie patched'
    });
  }
  catch(error){
    next(error);
  }
});

Reutilice el m茅todo del servicio que use para el put porque necesitaba lo mismo que hace ah铆: devolver el id de la pel铆cula

async updateMovie(){
  const movieUpdated = await Promise.resolve(moviesMock[0].id);
  return movieUpdated;
}

![](

Challenge complete: 馃槂

/router/movies.js

  router.patch('/:movieId', async (req, res, next) => {
    const { movieId } = req.params;
    const { body: movie } = req;

    try {
      const updatedMovieItem = await moviesService.updateMovieItem({
        movieId,
        movie,
      });
      res.status(200).json({
        data: updatedMovieItem,
        message: 'movie updates item',
      });
    } catch (err) {
      next(err);
    }
  });

/services/movies.js

 async updateMovieItem() {
    const updatedMovieItem = await Promise.resolve(moviesMock[0].id);
    return updatedMovieItem || {};
  }

Mi soluci贸n

**Routes**
router.patch('/:movieId', async (req, res, next) => {

    const { movieId } = req.params;
    const { body: movie } = req;

    try {
      const patchedMovieParam = await moviesService.patchMovieParam({ movieId, movie });

      res.status(200).json({
        data: patchedMovieParam,
        message: 'movie param patched'
      });
    } catch (e) {
      next(e);
    }
  });

**Service**
  async patchMovieParam(){
    const patchedMovieParam = await Promise.resolve(moviesMock[0].id);
    return patchedMovieParam;
  }

Challenge:

    router.put('/:idMovie', async function(req, res, next) {
        const { body } = req;
        const { idMovie } = req.params;

        try {
            const movie = await movieService.remplaceMovie({ body, idMovie });
            res.status(200).json({
                data: movie,
                message: 'movie remplaced'
            });
        } catch (error) {
            next(error);
        }
    });

    router.patch('/:idMovie', async function(req, res, next) {
        const { body } = req;
        const { idMovie } = req.params;

        try {
            const movie = await movieService.updateMovie({ body, idMovie });
            res.status(200).json({
                data: movie,
                message: 'movie edited'
            });
        } catch (error) {
            next(error);
        }
    });

Crear铆a un m茅todo helper para crear la Promise, as铆 no se repetir铆a mucho c贸digo.

Reto:

router.patch("/:movieId", async function (req, res, next) {
        const { movieId } = req.params;
        const { body: movie } = req;

        try {
            const patchedMovie = await moviesService.patchMovie(movieId, movie);

            res.status(200).json({
                data: patchedMovie,
                message: "movie Patched"
            })
        } catch(e) {
            next(e)
        }
    });

// service

async patchMovie() {
        const patchedMovie = await Promise.resolve(moviesMock[0].id);
        return patchedMovie;
    }

// Route
router.patch('/:movieId', async function(req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
      const updatedMovieId = await moviesService.updateMovie({ movieId, movie })
      res.status(200).json({
        data: updatedMovieId,
        message: 'Movies Updated'
      })
    } catch(err) {
      next(err);
    }
  });
// service
async replaceMovie() {
    const replacedMovie = await Promise.resolve(moviesMock[0]);
    return replacedMovie;
  }
 router.patch('/:movieId', async function(req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
      const patchedMovie = await moviesService.patchMovie({ movieId, movie });

      res.status(200).json({
        data: patchedMovie,
        message: 'movie patched'
      });
    } catch (error) {
      next(error);
    }
  });

// service

 async patchMovie() {
    const patchedMovieId = await Promise.resolve(moviesMock[0]);
    return patchedMovieId || {};
  }
// METODO PATCH PARA ACTUALIZAR LA PROPIEDAD DE UN ELEMENTO
    router.patch("/:movieId", async function(req, res, next){
        const { movieId } = req.params;
        const { body: movie } = req;
        try {
            const updateMovieId = await moviesService.updateMovie({ movieId, movie });

            res.status(200).json({
                data: updateMovieId,
                message: 'movie property updated'
            });


        } catch (error) {
            next(error);
        }
    });

Al hacer post o put me saltaba un error de una promesa no controlada, el problema es porque recib铆a par谩metros por el body pero no los identificaba. Lo solucion茅 agregando la siguiente l铆nea de c贸digo en el index antes de las rutas:

app.use(express.json());

Reto:


    router.patch("/:movieId", async function(req, res, next) {
        const { movieId } = req.params;
        const { body: movie } = req;
        try {
            const partialUpdatedMovieId = await moviesService.partialUpdateMovie({ movieId, movie });

            res.status(200).json({
                data: partialUpdatedMovieId,
                message: 'Movie partial updated'
            });
        } catch (err) {
            next(err);
        }
    });

Para tener los iconos de las carpetas y archivos, pueden a帽adir la extensi贸n Material Icon Theme

/routes

//routes
<
     router.patch('/:movieId', async function (req, res, next) {
          const { body: movie } = req;
          const { movieId } = req.params;

          try {
               const patchedMovieId = await moviesService.patchMovie({ movieId, movie });

               res.status(204).json({
                    data: patchedMovieId,
                    message: 'movie patched'
               })

          } catch (err) {
               next(err)
          }
     })>

//services

<  async patchMovie() {
          const patchedMovie = await Promise.resolve(moviesMock[0].id)
          return patchedMovie;
     } >

Buenos enlaces, pas茅 horas estudi谩ndolos y entendi茅ndolos jaja

Challenge:

Ruta:

router.patch('/:movieId', async function(req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;

    try {
        const updatedMovieId = await moviesService.partialUpdateMovie({
            movieId,
            movie
        });
        res.status(200).json({
            data: updatedMovieId,
            message: 'Movie Updated'
        });
    } catch (err) {
        next(err);
    }
});

// Service:
async partialUpdateMovie() {
const replacedMovie = await Promise.resolve(moviesMock[0]);
return replacedMovie;
}

router.patch('/:movieId', async (req, res, next) => {
        const { movieId } = req.params
        const { body: movie } = req

        try {
            const reempMovieId = await MovieServices({ movieId, movie })
            res.status(200).json({
                data: reempMovieId,
                msg: 'movie reemplazada'
            })
        } catch (err) {
            next(err)

        }

    })

Services

async patchMovie(){
        const reempMovieId = await Promise.resolve(moviesMock[0].id)
        return reempMovieId || {}
    }

Mi soluci贸n al reto:

router.patch("/:movieId", async function(req, res, next) {
        const { movieId } = req.params;
        const { body: movie } = req;
        try {
            const replacedMovieId = await moviesService.updateMovie({
                movieId,
                movie
            });
            res.status(200).json({
                data: replacedMovieId,
                message: 'movie replaced'
            });
        } catch (error) {
            next(error);
        }
    });

Reto:

router.patch('/:movieId', async (req, res, next) => {
    const { movieId } = req.params
    const { body: movie } = req
    try {
        const updatemovieId = await moviesService.partialUpdateMovie({
            movieId,
            movie
        })
        res.status(200).json({
            data: updatemovieId,
            message: 'movie update'
        })
    } catch (err) {
        next(err)
    }
})
router.patch('/:movieId', async (req, res, next) => {
        try {
            const { movieId } = req.params
            const { body: movie } = req
    
            const updatedSpecificMovie = await movieService.patchMovie(
                { 
                    movieId,
                    movie 
                }
            )

            res.status(200).json({
                data: updatedSpecificMovie,
                message: 'Updated Movie'
            })
        }
        catch(error){
            next(error)
        }
    })

<h1>Challenger</h1>

<h2>Services</h2>

  async replacedMovie(movieId, movie) {
    let replacedMovie = await Promise.resolve(moviesMock[0].id);
    return replacedMovie || {};
  }

<h2>Router</h2>

router.patch('/:movieId', async (req, res, next) => {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
      const replacedMovieId = await moviesServices.replacedMovie({
        movieId,
        movie
      });
      res.status(200).json({
        data: replacedMovieId,
        message: 'Updated Movie'
      });
    } catch (err) {
      next(err);
    }
  });

Que son servicios?
Que es la l贸gica de negocios?

Soluci贸n al Reto propuesto:
Servicio:

async replaceMovie () {
        const replaceMovieId = await Promise.resolve(moviesMock[0].id);
        return replaceMovieId;
    }

Ruta:

router.patch("/:movieId", async function (req, res, next) {
    const { body: movie } = req;
    const { movieId } = req.params;
    try {
      // const updatedMovieId = await Promise.resolve(moviesMock[0].id);
      const replacedMovieId = await moviesService.replaceMovie( { movieId, movie });

      res.status(200).json({
        data: replacedMovieId,
        message: 'Movie reeplaced...!!'
      })
    } catch(err) {
      next(err);
    }
  });


  router.patch('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { body: movie } = req;
      const replacedMovie = await movieService.replacedMovie({ id, movie });
      res.status(200).json({
        data: replacedMovie,
        message: 'replaced movie Successfully',
      });
    } catch (error) {
      next(error);
    }
  });
  async replacedMovie() {
    const replacedMovie = await Promise.resolve(moviesMock[0].id);
    return replacedMovie || [];
  }

A mi me gusta exportar la instancia del servicio de la siguiente forma y as铆 tengo un singleton del mismo.

module.exports = new MoviesService();

...

const moviesService = require('../services/movies.service');

const movies = await moviesService.getAll();

Buenas noches!, perdon pero no estar铆a entendiendo una cosa.
Por ejemplo, cuando Router.Put trae informacion de REQ, dentro del TRY se la esta enviando a moviesService.updateMovie? o recibiendola del servicio???, muchas gracias y saludos!.

Se parece a ANGULAR

En el curso de nodejs con Carlos se usa MVC, en qu茅 caso s铆 y en qu茅 no?

Router

Service

Challenge

router.patch('/:movieId', async (req, res, next) => {
    const { movieId } = req.params;
    const { body: movie } = req;
    
    try {
      const movieUpdated = await movieService.update({ movieId, movie });
      res.status(200).json({
        data: movieUpdated,
        message: 'movie updated'
      })
    } catch (error) {
      next(error);
    }
  });

Reto:
routes/movies.js

  router.patch('/:movieId', async function(req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
      const patchedMovieId = await moviesService.patchMovie({ movieId, movie });
      res.status(200).json({
        data: patchedMovieId,
        message: 'movie patched'
      });
    } catch (err) {
      next(err)
    }
  });

services/movies.js

  async patchMovie() {
    const patchMovieId = await Promise.resolve(moviesMock[0].id);
    return patchMovieId || [];
  };

Routes

router.patch("/:movieId", async function(req, res, next) {
        const { movieId } = req.params;
        const { body: movie } = req;
        try {
            const patchedMovieId = await moviesService.patchMovie({ movieId, movie });
            res.status(200).json({
                data: patchedMovieId,
                message: 'movie patched'
            });
        } catch (err) {
            next(err);
        }
    });

Service

async patchMovie() {
        const patchedMovieId = await Promise.resolve(moviesMock[0].id);
        return patchedMovieId;
    }

el peor profesor de toda la carrera de JS

Si en el m茅todo PUT (el servicio updateMovie) solo necesita el id porque incluimos el body del request?

const updatedMovieId = await moviesService.updateMovie({movieId, movie //este de aqu铆})```

el servicio solo necesita un id



async updateMovie(){
const updatedMovieId = await Promise.resolve(moviesMock[0].id)
return updatedMovieId
}```

Gracias companeros

Reto
capa de servicios:

    async editedMovie() {
        const editedMovieId = await Promise.resolve(moviesMock[0].id);
        return editedMovieId;
    };```
capa de rutas:


router.patch('/:movieId', async function(req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
        const deleteMovieId = await moviesService.deleteMovie({ movieId, movie })
        res.status(200).json({
            data: deleteMovieId,
            message: 'movie edited',
        });
    } catch (error) {
        next(error);
    };
});

Si el servicio se encarga de la l贸gica creo que quedar铆a mejor as铆:

Rutas鈥

router.get('/', moviesService.getMovies);
router.get('/:movieId', moviesService.getMovie);
etc...

Servicio

class MoviesService {
  async getMovies(req, res, next){
    const { tags } = req.query;

    try {
      const movies = await Promise.resolve(moviesMock);

      res.status(200).json({
        data: movies,
        message: 'Movies listed'
      });

    } catch(error){
      next(error);
    }
  }
}
etc...

Creo que queda mejor, m谩s legible y el archivo de rutas solo se encarga de hacer 鈥渕atch鈥 de la ruta. De la l贸gica se encarga el servicio.

De acuerdo a como lo hicimos en la clase, as铆 implement茅 el verbo PATCH.

Routes鈥

router.patch('/:movieId', async function(req, res, next){
    const { movieId } = req.params;
    const { body: movie } = req;

    try{
      const updatedSingleMovie = await moviesService.updateSingleMovie({movieId, movie});

      res.status(200).json({
        data: updatedSingleMovie,
        message: 'Content movie updated'
      });
    } catch(error){
      next(error);
    }
  });

Service鈥

async updateSingleMovie(){
    const updateSingleMovie = await Promise.resolve(moviesMock[0].id);
    return updateSingleMovie;
  }```

Challenge resuelto 馃槃
Services

Routes

aveces quisiera entender 馃ゴ

As铆 realic茅 el reto:

router.patch("/:movieId", async function (req, res, next) {
  const { movieId } = req.params;
  const { body: movie } = req;

  try {
    const patchedMovie = await moviesService.patchMovie({
      movieId,
      movie
    });
    res
      .status(200)
      .json({
        data: patchedMovie,
        message: 'Movie deleted'
      })
  } catch (err) {
    next(err);
  }
});
async patchMovie() {
  const patchedMovieId = await Promise.resolve(moviesMock[0].id);
  return patchedMovieId;
}

service

async updatePartialMovie(){
        const updateMoviePartialId = await Promise.resolve(moviesMock[0].id);
        return updateMoviePartialId;
    }

route

router.patch('/:movieId', async function (req, res, next) {
        const { movieId } = req.params;
        const { body:movie } = req; //al deestructura le ponemos un alias al objeto

        try {
            const updatedMoviePartialId = await moviesService.updatePartialMovie({
                movieId,
                movie
            });

            res.status(200).json({
                data: updatedMoviePartialId,
                message: 'movies updated partial'
            });
        } catch (error) {
            next(error);
        }
    });

Es un anti patr贸n, faltar铆a agregar la layer repository, si me equivoco me lo pueden hacer saber, se acepta un feeback.

Mi soluci贸n al desaf铆o:

router.patch("/:moviesId", async function (req, res, next) {
    const { movieId } = req.params;
    const { body: movie } = req;
    try {
      const partialUpdatedMovieId = await moviesService.partialUpdateMovie({
        movieId,
        movie,
      });
      res.status(200).json({
        data: partialUpdatedMovieId,
        message: "movie partially updated.",
      });
    } catch (err) {
      next(err);
    }
  });```



async partialUpdateMovie() {
const partialUpdatedMovieId = await Promise.resolve(moviesMock[0].id);
return partialUpdatedMovieId || {};
}```

Aqui el libro de Clean Architecture, muy famoso -> clean architecture


// PATCH
router.patch('/:clientId', async (req, res, next) => {
  const clientId = req.params;
  const { body: client } = req;

  try {
    const updatePatchClientId = await clientsService.updatePatchClient({
      clientId,
      client,
    });
    response.success(req, res, updatePatchClientId, 200, 'client updated');
  } catch (err) {
    response.error(req, res, 'Internal error', 500, err);
    next(err);
  }
});```

Services.js

async patchMovie() {
        const patchMovieId = await Promise.resolve(moviesMock[0].id);
        return patchMovieId;
    }

Routes.js


    router.patch('/:movieId', async function (req, res, next) {
        const { movieId } = req.params;
        const { body: movie } = req;

        try {
            const patchMovieId = await moviesService.resolve({ movieId, movie });

            res.status(200).json({
                data: patchMovieId,
                message: 'movie updated patch'
            });
        } catch (err) {
            next(err);
        }


    });

Asi quedo mi implementacion del metodo patch en nuestras rutas

   router.patch("/:movieId", async function (req, res, next) {
      const { movieId } = req.params;
      try {
         const patchedMovieId = await movieServicies.patchMovie({ movieId });

         res.status(200).json({
            data: patchedMovieId,
            message: 'Movie Patched'
         })
      } catch (err) {
         next(err);
      }
   })

Y en la parte de los servicios

   async patchMovie() {
      const patchedMovieId = await Promise.resolve(moviesMock[0].id);
      return patchedMovieId;
   }

=)

馃挏馃挏鈽鈽
Los controladores se conectan al API este recibe o envia un JSON.


馃挏馃挏鈽鈽
Es el coraz贸n de nuestra
aplicaci贸n
esta toda la l贸gica de negocio. Muy Importante馃敟 = Los controladores no llaman a otros controladores, pero los servicios si pueden llamar otros servicios y librerias.


馃挏馃挏鈽鈽
Son la capa que esta adjunta a la libreria externa como por ejemplo, bases de datos, bases de datos que estan en la nube e incluso nuestras API麓s.


::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Implementaci贸n Capa de Servicios
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::