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:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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 “match” 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
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::