logo

midudev


Transcribed podcasts: 146
Time transcribed: 5d 9h 42m 56s

This graph shows how many times the word ______ has been mentioned throughout the history of the program.

¿Qué vamos a hacer ahora? Lo que vamos a hacer es conectar nuestro servidor de GraphQL a MongoDB
de forma que vamos a ver qué potencia tiene GraphQL a la hora de conectarlo con una base de datos
y vamos a ver que es sencillísimo, que es bastante rápido
pero una vez que lo tengamos conectado vamos a ir pues iterando, vamos a ir ampliando la funcionalidad
hasta que hagamos una pequeña administración de usuarios
y una vez que tengamos eso, pues vamos a ver qué reto nos podemos encontrar
donde deberíamos poner la gestión del token en GraphQL
así que si os parece, vamos al código
yo ya tengo aquí mi proyecto que ahora os enseñaré, como lo dejamos la última vez
el servidor de GraphQL, teníamos aquí ya mutaciones y queries
si no sabéis lo que es una mutación y una query, pues lo explicamos en las anteriores clases
pero bueno, ahora mismo tampoco te creas que es muy importante porque nos vamos a enfocar en otras cosas
ahora lo que vamos a hacer es ir a nuestro proyecto, al servidor, que lo tengo que tener por aquí
vale, aquí lo tengo, a ver si me deja moverlo, aquí
y teníamos pues un index.js
y aquí, ¿qué más teníamos?
bueno, aquí tenemos todas las personas, ahora mismo lo estamos haciendo todo a saco
esto, teníamos un objeto directamente en nuestro GraphQL server
pero esta no es la forma correcta de la que deberíamos hacer este tipo de cosas
lo que deberíamos hacer es tener una API o tener una base de datos
que es lo que vamos a hacer justamente ahora
este servidor es el que tengo levantado aquí en el puerto 4000 que es el que te acabo de enseñar
este de aquí, ¿vale? donde ya podríamos hacer pues todo lo que son, pues nada
all persons, devuélveme todas las personas que tengan teléfonos
le doy al play y aquí las tengo, ¿vale?
a mi dev y da pelo
pero esto va a cambiar totalmente porque vamos a pasar todo esto a MongoDB
de forma que ahora en lugar de tener estas personitas por aquí
lo que vamos a hacer es tenerlo en MongoDB
¿cómo funcionaría esto? ¿cómo lo vamos a hacer?
ya hicimos una clase donde nos enfocamos al máximo con MongoDB
así que seguramente muchas de las cosas de MongoDB las vamos a pasar un poco por encima
así que vamos a instalar primero la dependencia de MongoDB
que sería, bueno, Mongoose
vamos a utilizar Mongoose que va a ser el cliente de MongoDB que utilizamos
y voy a instalar también de Mongoose el Unique Validator
que luego verás para qué sirve
pero básicamente es para asegurarnos que los paquetes
los paquetes no, los documentos que añadimos a la colección son únicos
según el campo que nosotros le digamos
de hecho vamos a verlo ya, vamos a crear una nueva carpeta
vamos a crear los modelos
y vamos a crear el modelo de la persona, de person, ¿vale?
person.js
y esto ya lo habíamos aprendido pero vamos a ir paso a paso
vamos a importar Mongoose de Mongoose
y ahora que hemos importado Mongoose vamos a crear el esquema de la personita
Mongoose.schema, ¿vale?
un esquema al final era muy parecido a lo que estamos haciendo con las type definitions
también de GraphQL
y aunque se solapan un poco
vamos a ver que no son exactamente lo mismo
y que es importantísimo tenerlos separados
por si el día de mañana esta base de datos dejamos de utilizar GraphQL o lo que sea
o sea, las validaciones estas tienen que existir y tienen que estar
no nos podemos fiar solo de las validaciones de GraphQL
además porque aunque es verdad que aquí, por ejemplo
la persona va a tener una propiedad name
de hecho lo tenemos aquí, ¿no?
teníamos name, font, street y city
aparte de la id
pues tendríamos el name y sería del type
pues sería string
le podemos decir que requerido
y lo que tenemos que decirle si es único
esto luego veremos cómo funciona
esto ya funcionaría, ¿eh?
en el plugin esto lo que haría es que evitaría
meter o introducir
otro documento en la colección que tenga
el mismo valor para este nombre
entonces le decimos que es único
solo que el pete es un poco raro
es como que peta bastante
y con el plugin lo que podemos hacer es que el pete sea mucho mejor
mucho más fácil de leer
y le decimos que la longitud mínima es 5
ahora voy a seguir añadiendo más propiedades
pero quiero enseñarte una cosa
con este esquema, fíjate, ¿no?
ya el nombre que es type string, required, no sé qué
estos dos de aquí sí que lo estábamos haciendo aquí, ¿no?
le decíamos que la persona en GraphQL
tenía que tener la propiedad name
y que fuese un string
y con la exclamación que era requerido
pero aquí además le estamos diciendo
que la longitud mínima tiene que ser de 5
o sea que tiene más validaciones
importante
de hecho luego veremos que esto
lo vamos a tener que controlar de alguna forma
voy siguiendo
type del font
vamos a poner que es un string
la longitud mínima también 5
¿qué más?
la calle
vamos a decirle que es de tipo string
que es requerido true
y el mínimo 5
y este, este de street sería lo mismo
pero en lugar de street, city, ¿vale?
así que esto ya tendríamos el esquema
le hemos dejado la que todos tienen que tener 5
bueno, city podemos hacerlo un poquito más pequeño
por si acaso
pero todos tienen una validación
de que la longitud mínima es 5
ahora lo que nos faltaría
es un export default
de mungoose model
le ponemos el nombre de nuestro modelo
y le pasamos el esquema
que tiene que utilizar ese modelo
¿vale?
así que con esto
ya tendríamos nuestro primer modelo
para la persona
a ver, voy a intentar añadir
el unique validator
a ver si funciona
porque mungoose
unique validator
unique validator
¿vale?
y el unique validator
si no, lo voy a probar
pero si nos da algún problema
pues lo quitaré
pero el unique validator
lo que deberíamos tener aquí
una vez que ya tenemos el esquema
tenemos que poner el esquema
punto plugin
y decirle que queremos utilizar
el unique validator
hay un montón de plugins
para tener más validaciones
¿vale?
esto es un plugin
que te añade una validación
que lo que va a hacer
es que cuando vea
que este campo no es único
pues te petará
pero te petará
de una forma que no te dirá
esta aquí
no sé qué
no sé cuánto
que es lo que te da
mungoDB por defecto
sino que te dirá
has puesto que este campo
tiene que ser único
y no lo es
y tal
es un poquito más fácil
de leer
vamos a dejarlo por aquí
el modelo de la persona
conexión de base de datos
venga
conexión de base de datos
vamos a hacerlo en un fichero aparte
le vamos a dar
db.js
necesitamos mongoose
esto
voy rapidillo
de mongoose
porque hay una clase
que hicimos
solo de mongoDB
así que
si no
si no sabes nada
de mongoose
a ver
no es importante
porque
solo con que vayas
entendiendo
que creamos un esquema
o cuando hagamos
los métodos de guardar
y tal
que te imagines
lo que hace
pero si quieres más detalles
que sepas que hay una clase
solo de mongoDB
que lo explico
vamos
al dedillo
vale
mongoDBURI
esto básicamente sería
el string de conexión
por ahora
lo voy a dejar vacío
pero luego añadiré
esto debería ser
un mongoDB
más srb
y barra
midudev
aquí el valpassword
y aquí el cluster
y bla bla bla
luego lo añado
porque
bueno
la contraseña
no quiero que la veáis
la pondría ahí directamente
esto se debería hacer
con variables de entorno
que en clases anteriores
lo hicimos
pero como hoy
nos queremos enfocar
en GraphQL
y la sección del usuario
como sería
con una base de datos
que puede ser la que queráis
esto puede ser
MySQL
lo que queráis
pues bueno
lo vamos a hacer
un poco más a saco
para ir avanzando
vale
voy a poner
bueno
el mongoDBURI
no lo voy a poner
no lo voy a poner
no
lo que voy a poner aquí
es mongoose.connect
le vamos a decir
a qué se tiene que conectar
bueno
pues se tiene que conectar
al mongoDBURI
y aquí había un montón
de campos
que teníamos que poner
para bueno
pues para configurar
la conexión
como que utilizase
el nuevo parser
le tenemos que decir
que utilice
esto son
esta configuración
hay mucha
que en realidad
es para que no nos salte
un warning
de que está deprecado
o lo que sea
vale
porque hay un montón
de opciones de estas
que por defecto
funcionan de otra forma
y entonces te aparece ahí
esto está deprecado
y no sé qué
y como nosotros
tampoco la vamos a utilizar
otras que son de optimización
como esta
que cuando se crea una colección
nos crea un índice
vale
pues una vez que tengamos
la conexión
solo para asegurarnos
como esto devuelve una promesa
vamos a poner
vale
ya estoy conectado
connected
tu mongoDB
y si no
pum
error
capa chao
pues vamos a ver
qué ha pasado
si da un error
nos vamos a poner esto
y
voy a poner error
connection
to mongoDB
mongoDB
y el error
punto message
y esto
ya lo tendríamos
a ver
que revise
solo me falta
el mongoDB URI
esto ya vimos
que en mongoDB
cloud
que es el que
estábamos utilizando
por si lo queréis ver
sería algo esto
esto es totalmente gratis
vale
es un mongoDB
que podéis tener
en la nube
le dais a connect
bueno aquí
no va a salir
los detalles
de mi contraseña
porque hay que darle
pero sería algo similar
a esto
veis
este sería la conexión
esto lo vimos
en una clase
aquí te aparecería
el string connection
y básicamente
pues ya lo tendríamos
pero aquí
hay que poner la contraseña
que me voy a llevar
este archivo
un momento
y lo voy a copiar
voy a copiar
la contraseña
que no es que no me fíe
o sea
yo me fío
fiar me fío
pero no tanto
a ver más que nada
porque si alguien
se pone en modo troll
nos puede tener aquí
todo el día
borrando cosas y tal
lo importante
es que he creado ya
el archivo db.js
que es el que se conecta
a la base de datos
tengo ya el modelo
tengo la conexión
a la base de datos
pues ahora
nos vamos al index.js
y vamos a empezar
a utilizar todas las cosas
que he creado
para empezar
vamos a importar
la conexión
a la base de datos
una cosa importante
de la conexión
a la base de datos
es que se hace
y ya está
una vez que la importas
los módulos
cuando tú los importas
tú puedes importar
el mismo módulo
80 veces
que solo se ejecuta
una vez
entonces por eso
podemos hacer esto
yo lo importo
de esta forma
y ese código
que he dejado
en la raíz
se va a ejecutar
una vez
y ya está
entonces se conectará
a la base de datos
o debería conectarse
y no deberíamos
tener ningún problema
vamos a importar
también el módulo
el módulo
módulo
módulo
del persona
y ya tendríamos
aquí person
con esta colección
este modelo
de person
ya podemos
guardar datos
hacer un montón
de cosas
de hecho
vamos a ir cambiando
hasta ahora
estamos utilizando
este objeto de aquí
que es un objeto
json y tal
pero esto es
caca de la vaca
fuera de aquí
porque ahora
vamos a utilizar
una base de datos
de verdad
y punto
pues entonces
el person count
lo que antes hacía
era devolver
el número
de elementos
que tenía la array
pero como ya no tenemos array
pues tenemos que ir
a nuestra base de datos
tenemos que utilizar
el modelo de person
punto
collection
y count documents
esto nos va a dar
el número de documentos
que hay en la colección
esto es para el person count
vamos a ver
el all persons
all persons
me voy a cargar todo esto
esto es lo que hacíamos antes
ahora el all persons
por ahora
a ver voy a hacerlo
primero
vamos a hacerlo a saco
y luego le añado el filtro
¿vale?
voy a poner aquí que
falta el filtro de font
porque antes
estábamos filtrando también
cuando hacíamos el all persons
podíamos mirar
si queríamos
todas las personas con teléfono
o sin teléfono
y claro
ahora lo que
tendríamos que cambiar
todo eso
por ahora voy a hacer
person punto find
y que me los encuentre todos
luego revisaremos esto
porque se tiene que cambiar
pero ahora
por ahora
cuando hagamos la query
de all persons
que nos devuelva
todas las personitas
y ya está
este find person
bueno
más o menos
se puede quedar igual
¿no?
lo que pasa es que devolver
tiene que ser
person punto find one
y aquí le pasamos name
que el name
es el que estamos recuperando
de los argumentos
hasta aquí bien
venga
ahora la mutación
este find
ya no tiene sentido
esto es para ver
si era único
esta validación
ya la estamos haciendo
en MongoDB
mucho mejor
que como la estamos
haciendo antes
así que esta validación
fuera
la realidad es que
para añadir una persona
lo único que tenemos que hacer
es crear la persona
con el modelo
o sea hacemos un new person
y le pasamos
todos los argumentos
¿vale?
los argumentos
es lo que le vamos a pasar
a la query
el nombre
¿ves?
va a llegarle
name
font
street
city
justamente lo que le queremos pasar
le vamos a pasar
todos los argumentos
que nos llegan
¿vale?
en un objeto
pues lo que vamos a hacer
es justamente
este spread
de el objeto
args
y ya está
a ver
si queréis
podríais hacer esto
recuperarlo de args
a mí
no me
¿sabes?
o sea
podéis hacer uno de los dos
o recuperar cada una
de las propiedades
y hacer esto
puede estar bien
esto podría evitar
bueno
es que
es que
GraphQL
va a hacer un chequeo
del esquema
ya de la query
y no dejará
que intentéis pasar
otra cosa
que no acepte
la query
por eso
no pasa nada
si hacéis esto
porque
incluso podéis hacer esto
directamente
pasarle directamente
los argumentos
porque no se van a mutar
tampoco
si os queréis quedar más tranquilos
podéis hacer esto
pero bueno
como prefiráis
como veáis
el tema es que cualquier cosa
en este caso funcionaría
crearíamos una nueva persona
utilizando el modelo
le pasamos todos los argumentos
el addPerson
si miramos la mutación
¿veis?
llegaría
name, phone, street y city
y una vez que tenéis eso
pues lo único que tendríamos que hacer aquí
es devolver el person.save
luego haremos validaciones
¿vale?
ahora estamos haciendo como
solo migrar a la base de datos
pero claro
cuando tocamos una base de datos
puede haber petes
puede haber problemas
luego controlaremos esos petes
esos problemas
¿por qué?
a ver os voy a hacer un pequeño spoiler
¿qué pasa con este addPerson?
aunque es verdad lo que os digo
de que no va a dejar
GraphQL
que le llegue en la mutación
otra cosa
que no sea el name
el phone
el street
y el city
pero fíjate que GraphQL
sí que puede dejar
que le pasemos un name
que tenga dos caracteres
y yo en el modelo
le he puesto
que el name
tiene que tener mínimo 5
por lo tanto el pt
me lo daría
cuando intente hacer
el punto save
¿vale?
o sea
súper importante
así que hay validaciones
que no va a poder hacer GraphQL
que las hace MongoDB
y que esto puede petar
luego lo vamos a volver a ver
si no lo has pillado ahora
no te preocupes
que luego lo volvemos a revisar
y me falta el edit number
madre mía
la que tenemos aquí montada
para el edit number
a ver
el edit number
voy a quitarlo todo
porque me parece más fácil
primero
el edit number
era editar el número de teléfono
de una persona
lo primero que tendríamos que hacer
es buscar la persona
¿vale?
aquí hay que utilizar un await
así que pasamos esta función
a async
además así podéis ver
que los resolvers
pueden tener funciones totalmente
ya lo vimos
que pueden ser async await
pero bueno
para que lo veáis
todavía más claro
así que vamos a buscar
la persona
una persona
que tenga el nombre
que le estamos pasando
por los argumentos
recuperaremos esta persona
y a esta persona
le vamos a cambiar
el teléfono
con el teléfono
que estamos pasando
por los argumentos
y ahora devolvemos
el person.save
que bonito
ha quedado mucho mejor
¿no?
aquí igual
a ver
no es importante
pero esto se podría extraer
este find person
se podría extraer
una función
y reutilizarla aquí
yo
la verdad
es que tampoco
lo recomiendo mucho
y os voy a explicar
por qué
¿vale?
hay que pensar
que los
a ver
a no ser que sea
un cacho muy grande
en este caso
es un cacho
ya ves
es una línea
¿qué pasa?
hay que pensar
que en GraphQL
los resolvers
pueden ir
a base de datos
totalmente distintas
o sea
nosotros a lo mejor
la query
la hacemos a una base de datos
y las mutaciones
la hacemos a otra
esto porque es un ejemplo
muy sencillo
pero normalmente
GraphQL
es una API muy grande
en la que quieres hacer
conexiones con un montón
de fuentes de datos
entonces
si empiezas a hacer
muchas abstracciones
de este tipo
¿sabes?
así pequeñas abstracciones
al final
te puede ser muy complejo
de mantener
cuando tiene que ser
un GraphQL muy vivo
si estamos hablando
de 15
30 líneas de código
pues seguramente
una abstracción
tiene sentido
pero cuando es así
que es una línea
yo os diría que
igual
no pasa nada
¿vale?
hay veces que
no pasa nada
por repetirse
¿ok?
en estos casos
¿vale?
cuando digo estas cosas
hay gente que se me vuelve
un loco
y digo
mira lo que ha dicho
pero ¿qué dice este hombre?
bueno
es mi experiencia
es mi experiencia
yo digo mi experiencia
y intento deciros
lo que a mí me ha funcionado
en la vida
¿vale?
ahora que tenemos esto
pues lo que podemos hacer
voy a
vale
¿qué no ha encontrado?
no puedo encontrar
el módulo persona
vale
me ha petado por esto
porque no puedo encontrar
el módulo person
ah
vale
me ha faltado
el punto js
el uid
este no lo utilizamos
así que fuera
a ver ahora
si esto ha hecho
vale
ha fallado la autenticación
pues empezamos mal
empezamos mal
voy a cerrar esto
voy a volver a abrir
a ver
si no le cambio
la contraseña
ya está
pero si
me está fallando
la autenticación
a ver
voy a mirar un momento
el de B
igual lo he puesto mal
igual tenía
es que tenía por aquí
la contraseña apuntada
pero a lo mejor
eso es otra contraseña
que me he inventado yo aquí
sabes que yo he puesto
esa contraseña
feliz y contento
y a lo mejor
no es esa para nada
a ver
vamos a buscar la contraseña
¿dónde tenía
la contraseña?
si no
la vuelvo a generar
como me dé mucha historia
la vuelvo a generar
mira
la voy a volver a generar
porque si no
igual estamos aquí hasta
vale
en connect
choose a connection method
MongoShell
a ver si
no
pero esto
no
MongoShell no
fuera
database access
eso
me do dev
edit
password
edit password
vale
me la copio
la pongo
creo que es esto
guardamos el usuario
lo malo es que ahora
hay veces que tarda un poquito
¿veis?
que pone aquí
estamos deployando tus cambios
a ver
normalmente no tarda mucho
pero
no estaré
ay
cajo en la leche
estaba en el proyecto
que no era
¿veis que tengo dos proyectos?
uno GraphQL
y otro proyecto cero
vale
vale
el problema
ahora ya sé lo que ha pasado
ya sé lo que ha pasado
lo que ha pasado
es que estaba utilizando
un string de conexión
diferente al que debía
no pasa nada
no pasa nada
a ver
go back
connect your application
¿veis?
este es el que tenía que haber
utilizado
y estaba utilizando
seguramente otro
bueno vamos a cambiar
esta contraseña
close
aquí no debería tener
colecciones
si no la porro
vale
no tengo conexiones
database access
edit
edit password
nueva password
copy
password
update
y ahora nos vamos
a
¿veis que está?
cuando está así
como que está
haciendo ese movimiento
el borde
es que se están
guardando los cambios todavía
porque esto como está en el cloud
pues tienes que llevar
los cambios al servidor
entonces
si me intento conectar ahora
pues igualmente
me petará
porque todavía no ha llegado
los cambios al server
vale vamos a poner esto
por aquí
ahora sí
vale
ahora sí que lo he puesto bien
ahora sí
pues vamos a ver si funciona
vamos a hacer la query
de all persons
voy a quitar esta
all persons
con la query
de recupérame de todas
personas
el nombre
y el teléfono
play
normal
no tengo personas
en la base de datos
vamos a intentar añadir
una persona
vamos a añadir
a jrgarciadev
vale
y que tiene el teléfono
123123
y nos va a decir
no te olvides
de rest
v1
vale
y esta persona
es de Bogotá
no lo sé
espero que no se me enfade
las mutaciones
pues es una person
que tiene como parámetros
y le vamos a pasar
el nombre
el teléfono
la calle
y vale
argentina
te he visto
te he visto
un rabillo del ojo
bueno
no sé
la ciudad argentina
es un poco raro
pero no pasa nada
y lo que hace
esta mutación
es que debería crear
en la base de datos
esta persona
y nos debería devolver
además
el nombre
el teléfono
la dirección
y todo esto
vale
muy bien
nos ha dicho que es de Buenos Aires
le damos al play
pues ya está
esto ha creado
esta persona
con esta información
si ahora le doy a
all persons
debería
veis
ahora tenemos
a jrgarcia
y aquí está una de las gracias
de graph fuel
ves
de todas las personas
devuelveme solo el nombre
pum
pues solo el nombre
además es predecible
porque si yo le digo
que me tiene que llevar
todas las personas
con el nombre
fíjate
el objeto es todas las personas
y con el nombre
no es como
en una API rest
que tú haces una
tú pides
pero no sabes
lo que te va a llegar
no tienes la certeza
desde el código
porque esta es la query
que tú estás haciendo
desde el código
es diferente
y además
que aquí podemos ver
pues ahora quiero
el teléfono
la dirección
y la idea
vale
y le damos al play
vale
address
ah porque address
tiene más de un campo
tenemos que sacar street
por ejemplo
vale
pues aquí tenemos ahora de nuevo
toda la información
esta es la gran magia
que tiene graph fuel
nos funciona la person
el all persons
vamos a intentar encontrar
a jr garcía
por el nombre
vale
le vamos a pasar
este es una query
que tiene una variable aquí
que se le estamos pasando
desde query variables
así que la ponemos aquí
a ver si nos lo encuentra
perfecto
nos lo ha encontrado
que nos encuentre
todas las personas
con teléfono o no
esto
ahora mismo
no está funcionando
o sea yo si pongo phone
no
pese a que jr garcía
sí que tiene teléfono
me sigue pareciendo
vale
esto lo vamos a arreglar ahora
y vamos a editar el teléfono
de jr garcía def
le vamos a poner el teléfono
mira aquí veremos
el problema que esto
nos debería petar
veis
porque
ha fallado la validación
pero fíjate
que el error
es internal server error
esto lo arreglaremos
vamos a poner por ahora
como el teléfono
es de 3 caracteres
y hemos puesto
la validación de 5
aquí es donde está
el problemilla
vale
entonces el phone
y vamos a ponerle más
ahora sí que ha editado
el teléfono
de hecho si ponemos
otro campo aquí
que sea phone
para ver
lo que nos devuelve
pues aquí lo tenemos
perfecto
si devolvemos a las personas
pues el teléfono
es el que hemos cambiado
nos funciona todo
vale
o sea fíjate
que en menos de media hora
hemos pasado
todo nuestro graphquare
todas las queries
sin tocar una línea
de
de lo que es el esquema
que es que eso es lo maravilloso
o sea eso es lo genial
no hemos tocado
ninguna definición
absolutamente nada
ninguna definición
sí que hemos tenido que tocar
obviamente los resolvers
porque los resolvers
son de donde resuelve
la información
si le hemos puesto
la base de datos
pero bueno
que no hemos tardado mucho
y ya está
ya está funcionando
ya tenemos todo
lo que teníamos hasta ahora
funcionando con una base
de datos
vamos a seguir construyendo
a partir de aquí
tenemos la conexión
tenemos todos los resolvers
hemos jugado con el playground
vamos a añadir ahora
el filtro del teléfono
vale
porque aquí en el all persons
os decía que tenía
aquí falta el filtro del font
bueno
súper fácil
vale
si
a ver
arcs.font
pues si return
person.find
vale
si no le pasamos
el teléfono
si arcs.font
es false
que nos devuelva
a todas las personas
vale
de hecho vamos a poner así
en una línea
y si no
lo que le podemos pasar
aquí en el find
le podemos decir
en el campo font
vale
el campo font
utilizamos la
esto es una propiedad especial
que tiene
MongoDB
que le podemos decir
si preguntarle
si un campo existe
y le vamos a decir
el campo font
si existe o no existe
dependiendo del valor
de arcs.font
por ejemplo
arcs.font
podría ser yes
o no
pues
si es yes
pues ya está
que me devuelva
si devuelve
o no devuelve
o sea
esto será false
o no
vale
si arcs.font
es no
esto será false
y entonces será
que no existe
si arcs.font
es yes
entonces será true
y entonces será
que sí que existe
con esto
nos debería funcionar
esto viene aquí
vale
era un enum
de yes o no
esto lo hicimos aquí
y este yes no
fíjate que lo teníamos
en la query
de all persons
de forma que el parámetro
podría ser sí o no
y era ese string de yes no
y esa sería un poco la magia
si guardamos los cambios
y nos volvemos a ver aquí
ahora que no tenga font
ves
ahora ya nos sale
si ahora le pasamos yes
pues sí que nos debería aparecer
y si no le pasamos ninguno
también nos debería aparecer
vale
porque hemos dicho
que si no le pasamos ninguno
nos devuelva
todas las personas
esto sería el tema
de añadir
el filtro del teléfono
vamos con el otro problema
que os he comentado
de la validación
porque cuando hemos añadido
un número de teléfono incorrecto
me estaba pegando esto
con un internal server error
vale
que de hecho estaba pensando
no sé si incluso
me tira abajo el servidor
que espero que no
pero ya veo que no
vale
en este caso
este internal server error
esto es muy feo
vale
aunque sí que al menos
te pone el mensaje y tal
os voy a decir
esto es una cosa
súper importante
vale
que muy poca gente entiende
y de hecho
el otro día entré
una página
y dije
madre mía
es que los despediría
a todos
a ver
hay un tema
como ingenieros
o como desarrolladores
no sé si decir
que es un tema
de seguridad
puede ser que sea de seguridad
también de seguridad
claro
a ver
cuando hay errores
hay que evitar
siempre
al máximo
dar un error
que ponga
al descubierto
tu infraestructura
vale
en este caso
imagínate que tú tienes
este error
y este error
es el que tú
le envías
al usuario final
claro
en este error
pues es como que
puedes ver
que es Mongoose
que MongoDB
que utilizas
NoModules
que no sé qué
no sé cuánto
o sea
si fuese un error
que puede llegarle
al cliente
tendrías que evitar
al máximo
que tuviese este tipo
de detalles
vale
y errores
del tipo
internal server error
ya es mala pinta
porque esto
siempre hay que cortarlo
de raíz
y hay que intentar
que internal server error
no ocurra
si hay internal server error
significa que no lo estás controlando
y está petando
indiscriminadamente
y luego además
lo que te diría
es que este mensaje
sí que puede tener sentido
porque además
te puede ayudar
a hacer validaciones
pero
si puedes evitar
que aparezca cualquier cosa
que es de Mongoose
o lo que sea
pues mejor que mejor
vale
porque eso significa
ah pues esta persona
utiliza MongoDB
no sé qué
bueno
a ver
que no significa
que lo vayamos a hacer
nosotros ahora bien
pero bueno
es que el otro día
es este típico tema
que tú entras en una web
y te sale error
en PHP
en la línea
no sé qué
y dices ostras
es que lo vi
y no sé en qué página
del gobierno
que me puso los nervios
y dije
madre mía
cuánto habrá costado esto
¿dónde deberíamos poner esto?
en el edit number
¿no?
en el edit number
ya teníamos
el problema este
lo que podemos hacer
a ver
esto es igual
al final el problema
está aquí
en el try await
sería aquí
en el person.save
porque si no encuentra
a una persona
esto
esto petar
no nos va a petar
sino que lo que puede ser
es que
o sí
sí que puede petar esto
no te creas
si find one
si no lo encuentra
a ver
¿qué pasa?
si no lo encuentra
vamos a poner
que no lo encuentre
a ver qué pasa
cancet property
o no
claro
pues también deberíamos
poner aquí
si no ha encontrado
a la persona
pues entonces
bueno
en realidad
esto debería ser un reto
porque ya sabéis
que en GraphQL
se supone
que tú
al hacer un edit number
no sé si deberíamos
debería hacer esto
este sería el comportamiento
esperado en GraphQL
si no encontramos
a esta persona
deberíamos devolver null
sé que es muy raro
pero así es la convención
¿ok?
así que lo primero
que deberíamos hacer
en este caso
sería esto
si no encuentro a la persona
pues no hago nada
ya está
devuelvo null
y punto
ahora
a partir de aquí
bueno
tenemos este person
esto se supone
que si hemos encontrado
a la persona
cambiaríamos a la persona
le cambiaríamos
el teléfono
y aquí lo que haríamos
es el try catch
intentaríamos
por un lado
salvar esto
hacemos una wait
importante
¿ok?
y aquí haríamos
el catch
del error
y aquí en el catch
del error
pues esto lo hicimos
el otro día
¿vale?
user input error
hay un montón de errores
que puedes hacer
en este caso
en el servidor de Apolo
pero
estamos utilizando
el user input error
luego utilizaremos otro
para que veáis
que tiene más de
más de un uso
¿vale?
y entonces le podemos pasar
cuáles son los argumentos
que le hemos pasado
que son incorrectos
para que lo muestre
y ya estaría
esto sería en este caso
bueno
no sé si he puesto esto
vale
sí
lo he puesto
creo que bien
esto
es que esto mismo
esto mismo
que hemos hecho aquí
que al final se podría
como hemos
como decía antes
¿no?
a ver
esto sí que puede tener sentido
de
esto sí que puede tener sentido
de
de hacerle una abstracción
¿vale?
porque
poner esto
cada vez que hacemos
un person save
cuando es exactamente lo mismo
pues es un poco raro
pero bueno
también es verdad
que en el user input error
podríamos ponerle más
más chicha
al error
pero bueno
yo si
en este caso
en esto
seguramente sí que haría
una abstracción
en mi
en mi opinión
ahora que no se nos olvide
que tenemos que devolver
la personita
¿eh?
porque en GraphQL
cuando se hace una mutación
tenemos que ser capaces
de extraer la información
que queríamos
¿vale?
veis aquí
las mutations
cuando tú haces esto
fíjate que devolvemos
estamos devolviendo
una persona
así que
eso lo tenemos que cumplir
si no cumplimos
la liamos
vamos a ver cómo queda
ahora esto
si no encuentra al usuario
¿vale?
fail to fetch
capa chao
ah
he puesto una wait
sin poner una sync
eso me pasa
por no utilizar
un linter
¿vale?
async aquí
y ahora sí que debería
ahora sí
¿vale?
¿vale?
este bien
y nuestro usuario
que habíamos creado
jrgarciadev
vamos
vamos
jrgarciadev
vale
pero fíjate
que ya
el error
es bastante diferente
¿veis?
es que es súper importante
parece una chorrada
¿vale?
sé que parece una chorrada
pero fíjate
el error ahora es
el mensaje
es este
la localización
el path
no sé qué
el código
bad user input
o sea
algo has introducido
que no está bien
y puedes ver
obviamente
el mensaje
pues es que la validación
ha fallado
porque la persona
no sé qué
pero ahora
no hay nada
que te indique
a ver
si sabes
de utilizar Mongoose
obviamente
obviamente
pues más o menos
por el validation
puedes olértelo
¿vale?
pero no tienes una traza
en la que aparezca
el error
de Mongoose
¿ok?
esto es importante
esto es importante
esto es lo que
a lo que tienes que aspirar
no
poner en
decirle a todo el mundo
ha petado
y ha sido culpa
de mi base de datos
a ver
por favor
¿por qué me interesa a mí
como cliente
que
que
que
te estás utilizando
MongoDB
o MySQL
o cosas así
¿ok?
entonces
por eso esto es importante
tenemos aquí toda la información
tenemos un stat trace
sí que tiene sentido
que sepa que
utilizamos GraphQL
porque a ver
se tiene que conectar
con un cliente de GraphQL
o sea
es normal
hasta ahí puede llegar la cosa
pero
que no le estamos poniendo
sabes
no estamos dejando ahí
a la vista
todas nuestras vergüenzas
con el tema
de la base de datos
vale
vamos con
usuario
e inicio de sesión
vamos a agregar
administración de usuario
va a ser un poco
pim pam
por ejemplo
vamos a saltarnos
el tema del password
y todo esto
pero
pero
bueno
yo creo que se va a entender
y está bastante bien
así que vamos con la administración
de usuario
por simplicidad
vamos a hacer que el password
pues todos los usuarios
tengan el mismo password
porque en otra clase
ya vimos como hacer
el tema del password
las comparaciones
lo del token
todo esto
vamos a hacerlo del token
vale
vamos a ver
el JSON Web Token
eso sí lo vamos a ver
porque me parece interesante
y porque es importante
que veamos cómo funciona
en GraphQL
vamos con ello
a ver
voy a cerrar esta ventana
que tengo por aquí en medio
y todo el rato
me está dando
se me está poniendo
en medio del chat
y me está poniendo nervioso
vale
entonces
para hacer esto
lo primero que podemos crear
aquí en models
vamos a crear el user
vamos a crear el user
y venga
importamos Mongoose
desde Mongoose
por cierto
habéis visto que el import
no me ha petado
que no fiabais de mí
el esquema
creamos un nuevo esquema
de Mongoose
Mongoose.schema
en mayúscula
y le decimos
que un usuario
pues un usuario
username
va a ser del tipo
string
que esto requerido
es true
que esto tiene que ser
único también
sí
obvio
bueno
min length 3
¿qué más puede tener
el usuario?
bueno
vamos a hacer que
la lista
los usuarios
puedan tener
una lista de amigos
como si fuese
Facebook esto
va a ser un poco
simplista
no vamos a hacer
aquí un Facebook
ni mucho menos
pero así además
vamos a ver
cómo podemos hacer
el populate
que esto lo vimos
en una clase anterior
es que todo vuelve
todo vuelve
entonces esta lista
de amigos
al final
¿qué va a ser?
en realidad
van a ser personas
por lo tanto
vamos a poner
que esto
de el friends
vamos a tener
una referencia
a persona
person
en este caso
es el modelo
que habíamos hecho antes
aquí
person
es este person
y le vamos a decir
el tipo
de la referencia
es con un object id
¿vale?
ahora que tenemos
el esquema
va a ser
un username
al final
o sea un user
lo que tiene
es su username
y luego
una lista de amigos
nada
ya está
no lo vamos a dejar así
no va a hacer
nada más
y luego
mongoose
punto
le decimos
punto model
user
y el esquema
que tiene que utilizar
con esto
ya hemos creado
nuestro user model
¿ok?
ya lo podemos utilizar
persona
tenemos el usuario
vamos a importarnos
aquí
user
from
punto
barra
models
user
punto
js
¿por qué me ha cambiado eso?
ahí quieto
vale
ya tenemos persona
y user
ahora tenemos que añadir
eso sí
en GraphQL
también estos tipos
teníamos el type
de person
pues vamos a crear
también el type
de user
y vamos a tener aquí
el username
que es un string
que sea obligatorio
vamos a tener
friends
que los friends
va a ser
un array
de personas
que va a ser obligatorio
y le vamos a poner
una id
que es del tipo id
y que también es requerido
que es obligatorio
esto para el usuario
además también
vamos a trabajar
con un token
que luego
bueno
ahora mismo
lo vamos a hacer
y el token
va a ser del tipo
pues token
y va a tener una propiedad
que es el value
que es un string
y que también
es obligatorio
esto los tipos
por supuesto
las queries
también vamos a añadir
una nueva
que vamos a llamarle
mi
para decir yo
yo mismo
que cuando lo llames
va a devolver
a un usuario
¿cómo va a funcionar esto?
a ver
lo vais a ir viendo
como lo voy a ir construyendo
pero vamos a crear
una query
que cuando reciba
un token
te va a devolver
la información
del usuario
esto es súper típico
o sea
tú estás en una aplicación
y lo que quieres es
devuélverme
la información
del usuario
que está logado
pues con esta query
lo vamos a conseguir
y ¿cómo le decimos
qué usuario es?
porque fíjate
que no tenemos
ningún parámetro
esto lo vamos a ver ahora
lo vamos a hacer
con un token
¿qué dónde le vamos a pasar?
¿por parámetro?
no
por parámetro no
ahora veremos por dónde
y antes de esto
claro
todavía no tenemos
lo que es el concepto
de usuario
¿por qué?
porque no los estamos creando
vamos a tener que crear
nuevas mutaciones
mutaciones
que significa
que vamos a manipular datos
¿y qué vamos a hacer?
pues un create user
que tenga como parámetro
pues el username
con un string
que es obligatorio
y esto nos devuelve
un user
¿vale?
súper importante
las mutaciones
en GraphQL
tienen que devolver
un dato
y no tiene que ser
un true o un false
sino que tiene que ser
un tipo
porque cuando hacemos
una mutación
de un usuario
por ejemplo
creamos un usuario
devolver el usuario
que hemos creado
nos va a permitir
como vimos
refrescar la cache
reflejar esos cambios
en la UI
y cosas así
y los usuarios
obviamente
pues se tienen que
logar
así que vamos a hacer
con el username
y con el password
que ahora veréis
de dónde sale
el password
¿y esto qué tiene que devolver?
bueno
cuando hace un login
pues lo que vamos a devolver
es el token
que es el token
que tendremos que utilizar
después
para el
la query del me
¿vale?
ya tendríamos un poco
la definición
de nuestros datos
de nuestros nuevos datos
tanto la definición
de nuevos tipos
el de user
el de token
una nueva query
dos nuevas mutaciones
¿vale?
esto sería un poco
como normalmente
funciona en GraphQL
el graph
que es como un grafo
es un grafo de datos
al final
¿no?
y tú vas haciéndolo
pues cada vez más grande
y vas creando conexiones
en el grafo
y cosas así
en este caso
el user
al final tiene una lista
de
como podemos ver aquí
ahora el user
tiene una lista
de friends
que son personas
y estas personas
vienen de este tipo
así que
vamos a instalar
que no se me olvide
vamos a instalar aquí
uy demasiado grande
JSON Web Token
que lo vamos a utilizar ahora
¿vale?
perfecto
vámonos
vámonos
a index.js
uy
aquí tengo música
vuelve música
vuelve
a ver
un momento
ahora
que se ha ido la música
de repente
vale
pues aquí vamos a importar
he importado user
ahí he puesto modelos
y estos models
vale
vamos a importar
JSON Web Token
from JSON Web Token
¿ok?
ahora que tenemos
el JSON Web Token
necesitamos un string
que sea una palabra secreta
bueno
a ver
palabra secreta
como creéis
debe ser un secret
aquí
tu palabra secreta
para generar
tokens
seguros
¿vale?
Twitch
lo importante
es que sea un string
que no sepa nadie
que sea lo suficientemente largo
para que tampoco nadie lo averigüe
pero puede ser esto
no hace falta
hacer cosas raras
lo ideal no es tenerlo en el código
esto tendría que ser una variable de entorno
también lo vimos en una clase anterior
como hacerlo una variable de entorno
vamos a crear las mutaciones
porque al final
bueno
también la query
en la query también tenemos que hacerla
pero vamos a empezar por las mutaciones
voy a recoger las que no nos interesan
para que sea más claro
¿vale?
y vamos aquí a crear la mutación
de created user
¿vale?
vamos a tener el root
los arcs
y esto debería hacer unas cuantas cosas
crear el usuario
eso para empezar
así que new user
el user es el modelo
que tendríamos en Mongoose
y lo que le tenemos que pasar
es el username
como hemos visto antes
así que arcs username
así creamos un usuario
en la base de datos
pero todavía no lo hemos guardado
¿vale?
para guardarlo
pues user.save
ahora
aquí os voy a enseñar
otra forma
de hacer el try-catch
¿vale?
no es por nada
podríamos hacer
una sync await
pero quiero que veáis
que también podemos manejar
promesas normales y corrientes
sin que await aquí
por ejemplo
¿qué se podría hacer aquí?
el user.save
al final
en lugar de hacer un try-catch
para controlar
el error este
que pueda tener aquí
podríamos hacer también
y de hecho
a veces
yo lo hago
y me gusta
porque queda bastante bien
con un punto catch
esto lo enseño
solo para que lo sepáis
¿es mejor uno que otro?
a ver
el mejor es el que más os gusta a vosotros
y quede elegible
y todo el mundo lo entienda
si hacéis cosas muy raras
pues igual
mal
pero a mí
a veces me gusta
porque
cuando tienes este tipo
de return
tener esto
y el catch
ya lo tienes ahí justo
como que puedes hacer
que sea más fácil
de leer a veces
yo lo enseño
y vosotros
pues lo que queráis
¿vale?
vamos a devolver un nuevo error
user
input
error
con el error message
¿vale?
y los invalid arcs
son los arcs
que le pasamos
si os gusta bien
si no os gusta
pues seguid haciéndolo
como de la otra forma
solo que sepáis
que se puede hacer
punto
ya está
este será para el create user
y ahora pues la de login
venga
login
tendríamos
root
root
arcs
y este vamos a hacerlo
con async await
que si no en el chat
ya la gente se me pone nerviosa
vamos a tener el usuario
¿no?
entonces
vamos a buscar
del user
vamos a encontrar
el usuario
que el username
sea el arcs username
¿ok?
ahora
si no tenemos
si no tenemos el usuario
o el password
esto es muy pirata
¿vale?
esto es muy pirata
pero
hay que avanzar
y además
así lo hacen también
en el bootcamp
porque ya lo hemos visto
esto
pero
en este caso
vamos a hacer
que el password
sea este
¿vale?
si el usuario
no pone este password
es que no ha entrado
esto
se hace de otra forma
deberíais
guardar
tenemos una clase
entera
dedicada a esto
pero por eso
no voy a hacer
todo otra vez
tendrías que tener
la base de datos
guardada
no el password
sino el hash
del password
utilizando pues
shadow156
bcrip
o lo que sea
si te interesa el tema
que es muy interesante
te recomiendo
que te mires
la clase
donde esto lo explicamos
al detalle
en este caso
pues lo que vamos a hacer
simplemente
es mirar
que el password
sea secret
o la
midu password
¿vale?
midu password
ya está
si ese no es el password
es que no
es que ha puesto mal
el password
y ya está
así que le decimos
que throw new
user
input
error
y le decimos
ground credentials
importantísimo
también
¿vale?
no le decimos
el usuario no existe
o la contraseña
es incorrecta
no
le decimos
te has equivocado
esto
no lo entiendo
no le damos pistas
a la gente
¿vale?
no le decimos
ah no
el password
le faltan
tres letras
no
no le decimos
si ya le decimos
que el usuario existe
ya al menos dice
ah el usuario existe
voy a seguir probando
y no vamos a hacer eso
ahora vamos a hacer
el user for token
¿vale?
este es el usuario
que vamos a guardar
en el token
esto también lo vimos
en la clase
username
que bueno
esto puede ser
user.username
o podríamos
esto también podría ser
de the args
porque ya sabemos
que es el mismo username
pero bueno
tanto el que hemos sacado
de la base de datos
como el que nos viene
de los argumentos
tiene que ser el mismo
y la idea
es user.
esto del guión bajo
esto es una cosa
de MongoDB
que las ideas
cuando vas a su colección
las tienen así
¿vale?
tú podrías crearlo
o generarlo de otra forma
pero si haces que lo genere
MongoDB
te lo genera así
pero a nosotros
nos interesa más
que sea así
también porque no queremos
que la gente
tenga por qué saber
que utilizamos MongoDB
y aquí vamos a devolver
pues un objeto
que sea value
porque en el tipo
del token
hemos dicho
que era un objeto
con la propiedad value
utilizamos el JSON Web Token
para firmar
este objeto
user for token
y utilizando
la palabra secretísima
esta que teníamos ahí arriba
que os he comentado antes
esta palabra
y con esto
cuando hagamos login
de un usuario
que hayamos creado
nos debería devolver
value
el token
de ese usuario
¿vale?
ahora lo probaremos todo
vale
tenemos el create user
tenemos esto
yo creo que podemos probar
a ver si esto funciona
¿no?
vamos a probar
¿qué deberíamos hacer primero?
a ver primero
deberíamos hacer
mutation
create user
y fíjate
username
vamos a poner
midudev
esto tiene que ser
con comillas dobles
midudev
y aquí vamos a
recuperar
username
no sé si funcionará
esto de friends
si nos dará algún problema
voy a darle
a ver qué pasa
vale
friends
vale
porque como es de un
hay que sacarle subtipos
pero bueno
no tengo friends
ahora mismo
no tengo amigos
no tengo amigos
mis amigos
no hay
una red vacío
vale
luego veremos
cómo añadimos amigos
¿vale?
pero aquí
lo interesante
es que ya he creado
el usuario
username
midudev
ahora mismo
esto de
o sea
no puedo ver
los usuarios
que tenemos
no he hecho una query
para ver los usuarios
luego veré
cómo puedo recuperarme
a mí mismo
utilizando el token
que voy a devolver
por ahora voy a hacer
una mutation
¿vale?
que sea la del login
una cosa interesante
que aquí hay gente
que puede pensar
¿por qué el login
es una mutation?
esa podría ser
una buena pregunta
no sé si la está haciendo
en el chat
voy a probar esto
y ahora lo leeré
en el chat
pero
hay que tener en cuenta
que el login
se tiene que considerar
como una mutation
porque se está creando
un recurso
en este caso
que es el token
y el token
digamos que tiene
un tiempo de vida
y está creándose
en algún sitio
piensa que el token
podrías guardarlo
en una base de datos
si quisieras
por lo tanto
en realidad
es una mutación
el hecho de que lo hagamos
en memoria
no significa
que sea una query
y ya está
¿vale?
así que importante
si tienes que hacer un login
añádelo como una mutación
vale
entonces
vamos a poner aquí
el del login
vamos a ver
lo que me encanta
de GraphQL
es el autocompletado
que yo no me acuerdo
ya las cosas que he puesto
no pasa nada
con autocompletado
fíjate
ya me dice
pues aquí password
he puesto
midu password
creo que era
midu password
creo que he puesto
midu password
sí
midu password
y aquí ahora
¿qué queremos?
pues el value
del token
le doy al play
y ha funcionado
¡ha funcionado!
no ha funcionado
vale
bien
el caso
este es nuestro token
nuestro JSON web token
que con este JSON web token
ahora
por ahora
vamos a dejarlo aquí
pero esto
va a ser necesario
para la query
que vamos a añadir
para recuperar
la información del usuario
porque necesitamos el token
este token
¿qué pasa con este token?
bueno
pues vamos a hacer
vamos a utilizar
una nueva cosita
que tenemos
en el Apollo Server
esto es una cosa
de Apollo Server
que es el servidor
que estamos utilizando
para crear nuestro GraphQL
hay diferentes servidores
en este caso
nosotros utilizamos
Apollo Server
porque es uno de los más típicos
y aquí había que pasarle
las definiciones de tipos
las type definitions
y los resolvers
los resolvedores
que son los que tienes que decirles
donde tienen que sacar
la información
de estos tipos
pues bien
hay una tercera propiedad
que debemos utilizar ahora
que se llama contexto
context
¿para qué sirve este context
y qué es lo que hace este context?
vale
este context
va a recibir una función
¿vale?
esta función
tiene un parámetro
bueno
tiene un objeto
como parámetro
y uno de ellos
el más importante
que le llega
es el de la request
la request
¿qué significa esto?
pues que esta función
se va a ejecutar
cada vez
que le llegue
una request
a nuestro servidor
de GraphQL
¿vale?
cada vez que hagamos
una petición
va a pasar
por esta función
entonces
¿por qué es importante?
¿por qué es interesante
este context?
porque podemos devolver
un objeto
a través de esta función
que va a estar disponible
en nuestros resolvers
¿y dónde va a estar disponible
en nuestros resolvers?
pues va a estar disponible
con un tercer parámetro
que hasta ahora
no estábamos utilizando
y esto
es lo que nos va a permitir
poder utilizar el token
y hacer que algunos
algunos resolvers
estén protegidos
de forma que
si un usuario
no tiene
la sesión iniciada
no le estamos pasando un token
pues no puede utilizar
ese resolver
y le digamos
no
tú no puedes utilizar
esta query
o esta mutation
o lo que sea
porque no tienes permisos
¿cómo lo hacemos?
ya os digo
vamos a hacer
que esto sea asíncrono
así que ya está bien
porque así sabéis
que el context
puede tener una función
asíncrona
lo primero que vamos a hacer
es ver
si en la request
¿vale?
si tenemos una request
vamos a ver
que en headers
authorization
vamos a devolverlo
¿vale?
vamos a hacer
vamos a guardar
en auth
si tenemos una request
vamos a devolver
de los headers
la authorization
que esto veremos luego
como se lo pasamos
¿vale?
y si no
es null
una vez que tenemos esto
si tenemos un auth
y además
el auth
lo vamos a pasar
to lowercase
¿vale?
para poder leerlo
más fácilmente
empieza
starts
with
bitter
¿vale?
esto ya lo vimos
que es
cómo se pasan
los tokens
en este caso
sería
bitter token
porque hay diferentes
formatos de tokens
este sería uno de ellos
¿vale?
si es ese tipo de token
lo que vamos a hacer
con esto
es decodificar
el token
así que
el decode token
sería
con el
json web token
hacemos un verify
y extraemos
la parte del token
porque ahora veremos
cuando lo enviemos
como lo enviamos
¿vale?
ya lo veréis más claro
pero antes
de verificarlo
tenemos que sacar
el token
y el token
está justamente
auth
.substring
7
no te preocupes
porque ahora
debes estar pensando
¿qué está haciendo
este chico?
¿qué está haciendo
este chico?
a ver
lo que pasa
es que el string
que nos va a llegar
va a ser así
bitter
bla bla bla
entonces
si contamos aquí
este string
1, 2, 3, 4, 5, 6, 7
y lo que queremos
es este token
de aquí
por lo tanto
lo que vamos a hacer
es un super string
vamos a extraer
vamos a quitar
esta parte de aquí
hay diferentes formas
de hacerlo
podríamos hacer
un replace
yo que sé
pero bueno
esto es muy claro
porque siempre
tiene que estar
en la parte 7
y más cuando hemos
hecho este
stars width
¿ok?
así que para que veas
de dónde sale
que si no luego
me decís
¿pero dónde sale esto?
y tenemos que utilizar
la palabra secreta
para hacer la decodificación
así que
una vez que tengamos
el token decodificado
pues lo vamos a hacer
el decodact token
hay que tener en cuenta
¿qué es lo que hemos metido
en el token?
pues aquí lo tenemos
este era nuestro token
teníamos el username
y teníamos la id
y esta información
cuando tenemos
este decodact token
podríamos buscar ahora
el usuario
podemos hacer una web
user.findby
y le podemos pasar
el
bueno podemos decirle
que lo busque directamente
por id
y entonces utilizar
el decodact token
.id
o podemos sacar
la id
directamente de aquí
y creo que queda
un poquito mejor
¿vale?
entonces encontramos
el user
el user
no el user
el user
que tenga la id
que habíamos guardado
en el token
¿vale?
y además podemos hacer
el populate
de friends
¿esto qué significa?
pues que
en el modelo
si os acordáis
de nuestro usuario
habíamos puesto
que teníamos amigos
entonces
aquí lo que debemos tener
es un array de amigos
un array de ids
cuando tengas
ese array de ids
con este populate
lo que hará
es ir a buscar
a nuestros amigos
y sacar toda la información
que necesitemos
¿vale?
así que
este usuario
con esta id
tráeme también
la información
de los amigos
y aquí
me lo vas a dejar
en el current user
y simplemente
ya devolvemos
el current user
con un objeto
¿vale?
hay que devolver un objeto
y ahora veremos por qué
claro
porque tiene que ser un objeto
y esto es todo lo que hacemos
no hace falta
que hagamos nada
este contexto
debería ejecutarse
solo si teníamos el token
si no
esta información
no la tendremos
y esto será una forma
también de verificar
¿no?
podremos hacer
if
current user
entonces es que
el usuario
tiene una sesión iniciada
o sea
nos ha pasado un token correcto
y todo ha funcionado bien
para que os hagáis una idea
para ver que esto funciona
y para asegurarnos
que lo hemos hecho
todo perfectamente
podemos ahora sí
utilizar y crear
la query
del me
¿vale?
donde vamos a tener
el root
el args
y vamos a tener
el context
que es el tercer parámetro
y aquí que tenemos que pasar
pues return
context
punto
current user
esto es todo
porque
este me
en realidad
solo lo deben
pasar
o sea
solo lo puede utilizar
gente
que
personas que tengan
la sesión iniciada
que nos hayan pasado
un token correcto
por lo tanto
si tiene un token correcto
habrá pasado por aquí
habrá recuperado
esta información
en current user
la ha dejado
con una propiedad
del contexto
y aquí
en el me
en el context
nos debería llegar
toda esta información
vamos a ver
si todo esto funciona
si tiene sentido
si no tiene sentido
vamos a verlo
vamos a hacer el login
¿vale?
el login
tendríamos todo esto
¿veis?
este es el token
ahora voy a crear aquí
una nueva query
que va a ser query
y vamos a poner
me
¿vale?
me
y vamos a ver
que puedo recuperar
el username
y puedo recuperar
los friends
y de los friends
voy a recuperar
el name
que ahora mismo
no tengo friends
no tengo friends
no tengo amigos
no importa
vamos a darle al play
vale
¿qué pasa?
que ahora mismo
me es null
no hemos encontrado
a nadie
¿por qué?
porque no le hemos pasado
ningún tipo de token
ni nada
vamos a pasarle el token
¿cómo se pasa un token
por cabeceras HTTP?
pues aquí hay que crear
un objeto
tendríamos la cabecera
authorization
y ahora
pues lo que hemos hecho
el bidder
y luego el token
y ahora con todo esto
si hemos hecho todo bien
le damos al play
y ahora sí
ha encontrado el usuario
es verdad
que no tiene amigos
porque todavía
lo hemos hecho
luego
lo iremos añadiendo amigos
y tal
pero
lo que sí que tenemos
es que ha encontrado
al usuario
pero fíjate
que yo en ningún sitio
estoy pasando el usuario
sino que le estoy pasando
el token
del usuario
que se ha logueado
antes
podríamos utilizar otro
podríamos intentar
a ver
vamos a ver
todas las personas
JR García
bueno
personas no
es que tendría que crear
otro usuario
vamos a ver en el chat
que ya me pregunta
si no se vuelve demasiado grande
y difícil de escalar
cuando empiezas a agregar
muchos resolvers
y type definitions
yo creo que no
a ver
por un lado
tened en cuenta
que yo
todas estas queries
mutations
que esto ya lo expliqué
en una clase
esto lo podríamos sacar
a archivos
¿vale?
eso por un lado
lo mismo con las definiciones
al final las definiciones
podríamos tenerlas
en diferentes archivos
y solo las definiciones
sobre usuarios
solo las queries
solo no sé qué
pero
tened en cuenta
que por más grande
que se vuelva
esto va a ser
mucho más controlado
que cualquier otra cosa
que puedas intentar hacer
¿por qué?
porque esto lo que
te está haciendo
es un contrato
que siempre te vas a referir
a estos datos
de la misma forma
si por ejemplo
tú intentas replicar esto
con una REST API
va a ser mucho
mucho mucho más complejo
especialmente si vas
desde diferentes
tipos de
de bases de datos
y tal
y tienes que hacer
algún match
y cosas así
¿vale?
bueno
no tiene por qué ser
biter
o sea
alguien me dice
oye
creo que es biter
en mayúscula
biter
no
puede ser en minúscula
sin ningún problema
no hay ningún problema
se puede poner
en mayúscula o minúscula
lo que sí que es una buena práctica
como esto se puede poner
en mayúscula o minúscula
o indiferente
es que vosotros
cuando hagáis este tipo
de check
¿veis?
lo que he hecho yo
to lowercase
y así
os olvidáis de problemas
en este caso
os olvidáis de problemas
to lowercase
pim pam
y ya está
es verdad
a ver
esto es un poco
pero es verdad
que al hacer
to lowercase
el token
es un poco más inseguro
¿vale?
porque
veis que tiene mayúsculas
y minúsculas
bueno
podríais
al menos poner
el stats width
pues podríais poner
el to lowercase
a lo mejor lo podríais hacer
solo con otra parte
pero bueno
tampoco es
me parece
súper súper
problemático
en este sentido
vale
o sea que ya tendríamos esto
tendríamos lo del me
ya estábamos usando esto
os he enseñado
cómo utilizar
http headers
vamos a verlo
en la lista de amigos
si os parece
¿vale?
para
vamos a eliminar
bueno
no sé si vale la pena
eliminar a las personas
que nos tienen una lista de amigos
porque lo que vamos a hacer
lo que vamos a hacer
es
que cada vez que un usuario
al crear una persona
el add person
que solo lo puedas hacer
si realmente
eres
un usuario
porque no te sentido
añadir a una persona
si no eres un usuario
¿vale?
entonces
vamos a hacer
que solo los usuarios
puedan añadir personas
y si no
se van a encontrar
con un nuevo error
que vamos a añadir
así que vamos a buscar
el add person
y es así de fácil
ya veréis
primero
¿vale?
creamos
bueno
podemos crear la persona
no sé si tiene sentido
crear la persona
vamos a hacer primero
que si
no tenemos
vamos a recuperar
el current user
del contexto
así que
tercer parámetro
context
¿vale?
si no tenemos
si no tenemos
un current user
entonces
tenemos que utilizarle
oye no
es que
throw new error
y aquí está
el nuevo error
authentication
error
¿vale?
hay diferentes errores
en Apolo Server
que podéis utilizar
lo podéis ver
en la documentación
y uno de ellos
es el de autenticación
¿vale?
así que podéis poner
not authenticated
punto
pelota
ahora
esto si el usuario
por lo que sea
pues no
no ha iniciado sesión
y tal
ahora esto debe
cambiar un poco
¿por qué?
porque
aunque cuando se añade
una persona
¿vale?
se añade la persona
en la base de datos
hasta aquí bien
pero
el usuario actual
en sus amigos
le vamos a añadir
el amigo
así que
vamos a hacer
un concat
de person
¿vale?
hasta aquí bien
ahora una vez
que ya tenemos
ese amigo
en el current user
lo que tenemos
que hacer
es guardarlo
¿ok?
y con esto
ya estaría
o sea
realmente
no tenemos
que hacer
mucha cosa más
esto para la person
ver
por un lado
si tenemos
un usuario
en el contexto
si no tenemos
un usuario
oye
no puedes
crear
la persona
lo siento
si la has podido
crear
pues voy a hacer
que sea tu friend
¿vale?
y te lo añado
vamos a ver
si alguien
ha dicho
que quiera ser
mi amigo
dice
¿no sería mejor
poner esa lógica
de authenticated
en un middleware
para no repetir
código en cada resolver?
no
bueno
en un middleware
a ver
si hablamos de middleware
como en el tema
de context
seguramente no
¿vale?
¿por qué?
porque hay resolvers
que vamos a querer
que no utilice
esta lógica
¿vale?
esta lógica
esta de aquí
lo que sí que puede
tener sentido
es que esto
lo hagamos
en una especie
de middleware
en una función
aparte
eso sí
si vemos que es una cosa
que se repite
pero tengamos en cuenta
eso
que al final
no es tanto
un middleware
para repetir
en cada resolver
sino que sería
para repetir
en aquellos resolvers
que sí que tiene
autenticación
que en este caso
ahora mismo
solo es este
o sea
no todos
van a tener
este tipo
de check
por ejemplo
el all persons
la query esta
pues no lo va a tener
o no tiene por qué
todas las mutaciones
tener este tipo
de check
por ejemplo
el create user
no tiene sentido
que tenga este check
pero sí
si vemos que la lógica
esta es muy tocha
pues tiene sentido
que al final
hagáis una
función
o le podéis llamar
middleware
y pasarle todo esto
para que devuelva también
justamente eso
si eso al final de la clase
lo podemos intentar mirar
para ver cómo haríamos
un middleware
pero solo que se utilice
en aquellas resolvers
que nos interesa
no en cada uno de ellos
porque si no
estaríamos haciendo de más
vale
entonces
este add person
ahora
si vamos aquí
y intentamos añadir una persona
vamos a ver si alguien
me ha dicho que
quiera ser mi amigo
a ver
alguien decía
que quería ser mi amigo
me ha dicho
alguien
resolutores
a ver
alguien me había
j87
mismo
j87
vale
que ha puesto aquí
el mejor pot hablaba
me imagino que es de barcelona
o cerca
que pasa
antes de hacer la mutación
me tengo que asegurar
que tiene el http headers
¿por qué?
porque claro
esto ahora lo tiene que hacer
una persona
que haya iniciado sesión
el problema además
es que
si lo intento
con este que he recuperado antes
seguramente no me funcione
porque se ha guardado
en memoria el token
que se había generado
pero como he hecho cambios
habrá refrescado
y lo que sea
así que vamos a intentar
loguearnos otra vez
me voy a copiar este token
nos vamos a la person
y aquí vamos a poner
authorization
me voy a copiar esto
me voy a copiar lo del login
más fácil
y vamos a cambiar el token
para utilizar el nuevo
¿vale?
voy a utilizar aquí
en el me también el nuevo
para ver que tengo aquí
¿vale?
me sale mi dudez
perfecto
ahora en add person
con este token
le doy al play
¿vale?
hemos añadido a esta persona
si me voy al me
ahora podemos ver
que tengo un amigo
fantástico
vale pues entonces
con esto lo que hemos conseguido
es que cuando un usuario
crea una nueva persona
se añade automáticamente
a su lista de amigos
a ver
esto podría ser un poco
ñe ¿no?
porque obviamente
el crearlo
significa que
si esa persona
está creada ya
¿qué pasa?
que ya no puedo añadirla
como amigo
o sea solo la persona
que crea a la persona
no tiene mucho sentido
lo que podemos hacer
es crear otra mutación
¿vale?
podríamos tener
tenemos add person
edit number
create user
login
y así además
podríamos ver
el tema este
de añadir algún tipo
de mail
del web y tal
antes de utilizar
el type
vale aquí
add as friend
y aquí
lo que tenemos que tener
un name
el string
y esto nos tendría
que devolver
el usuario
¿vale?
el usuario
¿por qué nos devuelve
el usuario?
esto es interesante
¿vale?
nos devuelve el usuario
porque el usuario
es el que tiene
el cambio
de la lista
de amigos
¿vale?
súper importante
siempre en las mutaciones
vamos a querer
devolver
ese dato
que es el que
recibe la mutación
y el que reciba
mutación aquí
cuando hacemos
el add as friend
es el usuario
porque en su lista
de amigos
ahora tiene un amigo
nuevo
y qué bonito
tener amigos nuevos
qué bonito
así que
venga
ahora vamos
con la mutación
qué bonito
mutación
tenemos el login
pues añadimos
el add as friend
teníamos el async
root
args
os voy a enseñar
aquí otra cosa
por si
porque a lo mejor
como lo he hecho antes
pues alguien
habrá pensado
vaya rollo esto
esto es un poco
lo mismo que hemos hecho aquí
y de hecho
lo voy a copiar por ahora
y luego pensamos
en una forma de hacer esto
esto del current user
¿veis?
es lo mismo
y entonces
un compañero
nos ha dicho
oye esto
lo estás repitiendo
todo el rato
o sea lo vas a recuperar
lo vas a repetir
todo el rato
es verdad
ahora veremos
cómo lo podemos arreglar
podríamos hacerlo
un montón de formas
pero bueno
ahora lo arreglamos
una cosa que alguien
puede decir
oye
es que este const
current user
que está sacando el context
no lo puedes hacer aquí
si lo puedes sacar
de aquí directamente
¿vale?
si os gusta más
lo tienes aquí en una línea
y ya está
sacáis del contexto
el current user
y pim pam
una vez que tengamos esto
a ver
una cosa importante
que deberíamos hacer
primero
si queremos añadir un amigo
es buscar a la persona
¿no?
hacemos una wait
del person
buscamos una persona
que su nombre
sea el mismo
que el que nos están pasando
por el argumento
¿vale?
hemos encontrado
esta persona
pues ahora tenemos que saber
si esa persona
realmente
ya es amiga mía
¿no?
a ver
non-friendly
already
added
o not
friendly
already
todavía no es
no es amistoso
conmigo
entonces
del current user
tendríamos que revisar
si friends
si incluye
bueno
claro
esto puede ser
un poco tricky
¿vale?
¿por qué?
a ver
vamos a hacer un fine
y ya está
no pasa nada
vamos a hacer un fine
de la lista de amigos
aquí tendríamos persons
no
esta sería la persona
¿no?
entonces si
vamos
en lugar de fine
podríamos hacer
some
¿vale?
some ¿no?
si tenemos
alguno
que el person
punto
barra
idea
sea
¿qué estoy pensando?
¿cómo nos devuelve esto?
¿cómo nos devuelve esto?
si no
a ver
si hacemos un map
y vamos a hacer
que cada persona
solo recuperemos
la id
podemos decirle
para saber
si la persona
que hemos encontrado
tiene esto
de aquí
así que
a ver
lo podríamos hacer
en mil formas
pero bueno
se me ha ocurrido esta
de los amigos
lo único que hago
es quedarme
solo con el punto
barra baja id
¿vale?
el guión bajo id
esto es de mongo
y ver si esa persona
se incluye
en este array
y ya está
y de esta forma
sabremos
si ha sido añadido
o no ha sido añadido
por eso
porque hemos apuesto
este al principio
así tiene más sentido
así sabremos
si no es amigo
si no es amigo
entonces lo añado
non friendly already
y lo tenemos que decir
con person
¿vale?
que al final
esto
si no es añadido
entonces lo añadimos
¿cómo lo añadimos?
currentuser
friends
tiene que ser igual
a currentuser
friends
punto concat
y añadimos
la persona
y una vez
que hemos añadido
la persona
a mi lista
de amigos
pues la guardamos
currentuser
punto save
vale
y ya podemos
devolver
el currentuser
¿por qué el currentuser?
porque lo hemos dicho
antes
en la mutación
¿vale?
en el tipo de la mutación
hemos dicho
que tenemos que devolver
un usuario
y el usuario
que tenemos que devolver
es el usuario
actual
así que
currentuser
add as a friend
perfecto
y ya estaría
¿no?
ya estaría
sí
yo creo que
ya estaría
vale
vamos a ver
si esto
ha funcionado
vámonos para
add as a friend
vámonos para aquí
ahora lo mismo
tenemos que hacer el login
copiarnos el token
añadir
una nueva mutación
uh
mutation
mutation
add as a friend
¿vale?
esto
le tenemos que pasar
el name
que el name
vamos a poner
voy a añadir
otra persona
claro
lo que pasa es que
si voy añadiendo personas
al final
siempre tienen que ser
los mismos
voy a crear
un usuario nuevo
que le voy a llamar
a ver
voy a ver
vuestros nombres
papapapam
ya podéis ver
que sí
que se van guardando
automáticamente
si yo cierro esta pestaña
del playground
y la vuelvo a abrir
se han guardado
todas las queries
y que se guarde
más allá de estos
no sé
no sé si se puede
exportar o algo
vaya
no sé si se pueden
llegar a exportar
o sea
sí que se puede copiar
el curl
pero no sé
ves
en la historia
tenéis aquí
todas las que habéis hecho
no sé si
se puede hacer
algo más que esto
¿sabes?
no sé si se puede decir
aparte de copiarla
que es lo más típico
copy curl
no sé
como tampoco me he encontrado
con ese ejemplo
o sea
la necesidad
de hacer
hacer algo más que esto
mira
baumanzone había hecho
una write
pues vamos a hacer
vamos a crear un usuario
que sea
bauman
baumanzone
¿vale?
y ahora con bauman
vamos a
logarlo
¿vale?
ahora tenemos el token
de bauman
así que deberíamos poder
añadir como amigo
utilizando
el token
de bauman
vamos a poner por aquí
el token
de bauman
vamos a mirar
el mi
¿vale?
bauman ahora mismo
no tiene amigos
no tiene amigos
bauman
pero vamos a solucionar esto
vamos a añadirle
como amigo
a
j87
¿vale?
y aquí
deberíamos recuperar
el username
de bauman
vamos a darle al play
¿vale?
a tasafriend
y fíjate que lo que me devuelve
es el usuario
baumanzone
porque es el que ha recibido
el cambio
de hecho
si pongo friends
aquí
debería también
devolverme los amigos
¿vale?
de friends
tenemos que recuperar
el name
por ejemplo
y aquí tendríamos
username
baumanzone
friends
name
j87
¿por qué puedo
esta mutación
ejecutarla otra vez?
si ya
¿sabes?
la puedo ir ejecutando
y estoy añadiendo
todo el rato
al mismo amigo
porque en nuestra mutación
estamos haciendo el check
de que si no
si es
si todavía no es nuestro amigo
la añadimos
pero si no es nuestro amigo
lo único que hacemos
es devolver el usuario
y ya está
así que es una forma
interesante de evitar
que pete
si el usuario
a ver si os interesa
hacer la revisión
de
no se puede añadir
porque ya está añadido
pues en lugar de
hacer aquí el if
y dejar aquí
pues aquí el else
podríais hacer un throw new error
y poner aquí
el usuario
no sé qué
podríamos mirar
si hay algún error
de apolo
que tenga sentido aquí
y hacerlo
y ya está
¿vale?
y con esto
ya tendríamos
el tema
de la mutación
de el
add as friend
así que ahora
ya podríamos añadir
amigos
bueno
hemos hecho
un montón de cosas
con la tontería
pero un montón
un montón
vamos a ver
React
vamos a ver
si todavía funciona
nuestra aplicación
que hace tiempo
que no la veo
npm run dev
¿vale?
madre mía
que rápido va Vite
Dios mío
¿vale?
era la UI
más fea
que seguramente
he parido
en mucho tiempo
¿vale?
era fea
no
lo siguiente
¿vale?
pero lo importante
es que tenía
unos cuantos formularios
y que todo parecía
funcionar bien
y todo esto
vamos a crear
un formulario
para que el usuario
se pueda
loggear
fácilmente
bueno
fácilmente
ya veremos
porque con esa UI
igual no es tan fácil
vale
vamos a crear aquí
loginform.jsx
import React
useState
useEffect
from React
vamos a importar
el useMutation
esto también lo vimos
en la clase anterior
¿no?
cómo se podía utilizar
el useMutation
que venía de ApolloClient
y vamos a importar
esto lo voy a crear ahora
la mutación
¿de dónde tengo que sacar
la mutación?
de queries
si no me equivoco más
tenía por aquí
queries ¿no?
¿me había sacado
las queries?
no
GraphQL queries
la había llamado
¿vale?
GraphQL
GraphQL queries
¿vale?
GraphQL queries
¿esto dónde está?
ah
porque la habíamos puesto
aquí
vale
habíamos puesto
source
cookies
esto porque dice
el ejemplo
de cómo tener
separadas
el tema de
por contexto
y todo esto
bueno
no me parece mal
no me parece mal
vamos a utilizar este
vea
GraphQL queries
vamos a crear las
GraphQL queries
punto J
S
esto es porque
en la anterior clase
os estoy explicando
el tema de
screaming architecture
y cómo os puede ayudar
crear carpetas
separadas por contexto
en lugar
de
por tecnología
entonces aquí tendríamos
la mutation
del login
esto tendríamos aquí
el username
que sería un parámetro
¿no?
que sería
un string
y tendríamos el
password
que esto debería ser un string
que también es obligatorio
voy a eliminar todo esto
para verlo mejor
esto utilizaría el login
con el username
que sería el username
que le estamos pasando arriba
por parámetro
y el password
que sería el password
que le estamos pasando arriba
y aquí
recuperaríamos el value
que es el token
que queremos guardar
el cliente
vale
esto por aquí
vamos con el login form
ahora sí que tendríamos
todo esto
const login form
creo que teníamos
el tema esto
de hacer errores
no sé si llamarle
notify error
notify error
y el set token
el set token
es porque vamos a guardar
el token
en la aplicación
aquí
vamos a hacer aquí
podríamos tener aquí
token
set token
use state
y podríamos tener
null
por ahora
y como por aquí
vamos a crear
el login
voy a añadirlo ya
login form
vale
login form
ahora lo añadiremos
un poco
vale
y le pasaremos
el set token
y todo esto
vale
login form
esto me da mucho palo
es que lo hemos hecho
tantas veces
me voy a copiar
el login form
vale
me lo voy a copiar
me lo voy a copiar
y os explico
un poco
esto es el estado
el estado del username
y del password
y el render
vamos a renderizar
un formulario
tengo por aquí
un formulario
que es que es justamente
lo que necesito
así que
me lo voy a copiar
un formulario
que cuando haga el submit
ejecutará el handle submit
vamos a tener un div
para el username
que cuando haga el cambio
del input
pues cambiamos el estado
esto lo hemos visto
en una clase
que hicimos un montón
de formularios
así que
por eso me lo copio
no por nada
porque es que esto
lo tenéis que tener
si habéis seguido
el bootcamp
lo tenéis que tener
más que sabido
y lo interesante aquí
es más graphql
que no esto
que estamos haciendo
del formulario
que seguro
lo habéis visto
80 veces
aparte de esto
ahora
lo que sé que voy a hacer
es lo interesante
porque esto ya
lo hemos hecho
en un montón de clases
por un lado
el tema del login
y el result
que vamos a tener
a utilizar la mutación
del login
que esta es la que he creado aquí
estoy utilizando
el useMutation
el login es el que he escrito aquí
que le llamo
all persons
vamos a ponerle login
vale
así importo bien
login
y esta mutación
cuando existe un error
lo que deberíamos hacer
el error
podríamos ejecutar
el notify error
este que le estamos pasando
por props
no sé
la estoy pasando todavía
pero si no recuerdo mal
ves
notify error
notify error
notify error
esto por si hay algún error
pues lo notificamos
y mostraba una notificación
por ahí arriba
y eso
al menos nos puede ayudar
ah bueno
claro
aquí había que sacar todo
porque el notify error
esto aquí
creo que viene con
el graphql error
punto
graphql errors
sacábamos el primero
y solo mostrábamos
el message
vale
entonces
cuando hagamos
el handle submit
handle submit
esto aquí
tendríamos el event
del formulario
y hacemos un event
prevent default
esto es súper necesario
porque si no haría un submit
directamente del formulario
pero ahora
hacemos el login
y le pasamos las variables
que necesitamos
que es la del username
y es la del password
esta la estamos sacando
de los inputs
vale
de estos inputs de aquí
del username de aquí
el password de aquí
o sea que lo tenemos
en el estado
haremos el login
y una vez que hacemos
el login
pues que vamos a hacer
este login
llama la mutación
el login se hará
irá bien o irá mal
no sé cómo irá
veremos
y aquí en result
es donde tendríamos
que tener justamente
el token
así que
use effect
vamos a ejecutar aquí
un efecto
que cuando cambie
el result
punto data
pues aquí podremos
recuperar el token
si tenemos un result
punto data
pues que podemos hacer
bueno
vamos a recuperar
el token
de
result
punto data
punto login
punto value
¿por qué?
porque el login
es el nombre
de la mutación
y value
es justamente
lo que teníamos aquí
o sea
esto es esto
¿vale?
fíjate
login
porque es el nombre
de la mutación
es que es lo que tiene
GraphQL
que es súper predecible
¿vale?
y value
es el valor
que tiene el token
y esto es lo que
tenemos que recuperar
y ya está
¿vale?
esto lo tenemos aquí
tenemos
a ver
esto lo podríamos poner
value
aquí token
como queráis
haríamos un set token
esto se lo vamos a pasar
por props
¿vale?
el set token
y lo vamos a guardar
en local storage
set item
font
numbers
app
bueno
user token
y aquí le guardamos
el token
como es un string
no tenemos que hacer
un json parse
ni nada raro
sino que simplemente
lo guardamos
y ya está
y esto ocurrirá
solo si tenemos
un result punto data
¿vale?
y cuando cada vez
que cambie el result punto data
ejecutaremos
el use effect
con esto lo deberíamos
estar guardando
en el local storage
que a ver
lo podríamos ver
no debería ser muy
complejo
a ver en qué
en el 3000
vale
me he cargado algo
vamos a ver
que me he cargado
que me he cargado
login form
vale
porque todo esto
lo estoy exportando
de forma así
y aquí deberíamos importar
login form
from
login form
vale
importamos el login form
lo utilizamos aquí
nos faltaría
lo de set token
pasárselo
como prop
este set token
es el que tenemos
aquí en el estado
¿vale?
aquí justamente
que por ahora
no estamos utilizando
el token
pero lo podríamos
utilizar después
porque luego veremos
cómo pasamos este token
una vez que lo guardamos
de alguna forma
tendríamos que
pasarle el token
y todo esto
vale
a ver
hasta aquí
bien
vamos a ver si al menos
mi app
ah venga
fail to resolve
a ver
qué le pasa
a este
barra
login form
ah
el login form
lo que se está quejando
es este
de este
porque lo he movido
esto
punto punto
barra
no
punto
barra
login
login
barra
graphql queries
ahí
ahora sí
debería estar
vale
entonces
mira este es el login form
este que hemos puesto aquí
estas son las personas
que tenemos
que justamente ahora
si te fijas
las está pillando
la base de datos
no hemos hecho nada
en nuestra cliente
no hemos hecho ningún tipo
de cambio
y esto ya está funcionando
y
es que esto es una de las
maravillas
que tiene graphql
que es totalmente
agnóstico
a donde está recuperando
los datos
entonces ves
estas personas
son las que tenemos
en la base de datos
ya
entonces tenemos
el username
midudev
y aquí
debería ser
midu password
no sé si era la que estaba
le damos
no se está cambiando
el formulario
pero al menos
deberíamos ver
si le doy a login
y me voy a application
y me voy a storage
local storage
vamos a ver
veis
aquí
veis que
me ha recuperado
este phone numbers
user token
y me ha añadido
aquí el token
a ver todavía
no hemos hecho
la parte de la UI
de que cambie
el formulario
o lo que sea
pero ha funcionado bien
y me ha devuelto
el token este
para el tema
del login
así que con eso
justamente ya
podríamos añadir
personas
o lo que sea
como podríamos
aquí el tema es
como podemos
hacer que este token
que ahora tengo
pues se lo podamos
pasar
a las
requests
porque si no
cuando yo cree
una persona
de hecho
debería petar
o sea
si yo ahora intento
crear una persona aquí
¿no?
si intento crear una persona
debería petar
porque no tengo
permisos
¿ves?
no está authenticated
o sea
me está dando bien
me está dando bien
el error
o sea
no está autenticado
para poder hacer
que esté autenticado
le tengo que pasar
el token
de alguna forma
voy a intentar hacerlo
como yo creo
que es la forma correcta
pero he visto
que en otro sitio
lo están haciendo
de otra forma
y me ha dejado
un poco así
como sorprendido
entonces
lo voy a probar
como yo recuerdo
que debería estar funcionando
y si funciona bien
y si no funciona
pues ya veremos
lo que hacemos
pero
lo interesante
cuando teníamos aquí
el link
este es el cliente
de Apolo
cuando lo estábamos
inicializando
teníamos el conectar
a DevTools
la caché de memoria
el link
que era
donde está el servidor
de GraphQL
que en este caso
era el puerto 4000
que esto debería ser
una variable de entorno
y aquí
deberíamos poder ser capaces
de pasarle
el headers
y en headers
deberíamos tener
la capacidad
de decirle
authorization
que lo recupere
el local storage
punto
get item
phone numbers
user token
bueno a ver
que incluso
puedes tener
una función
aquí
puedes get out
y creo que
ya sé
porque esto
a lo mejor
no
o sea
sí que funcionará
pero a lo mejor
no funciona
tan bien
como nos gustaría
ahora lo veremos
vamos a recuperarlo
del local storage
que es donde se supone
que tenemos
token
vale
vamos a devolver
si tenemos el token
pues vamos a devolverlo
con bearer
y el token
vale
y si no
pues null
y este get out
lo podemos poner
aquí
así
de esta forma
vale
vale
esto sería get out
se ejecutará
tenemos este get out
y ya lo tendríamos
ahora
no gracias
no quiero guardar
mi contraseña
vamos a mirar
si todavía lo tengo
en el local storage
veo que lo tengo
vamos a ver
si soy capaz
ahora de ejecutar
aquí esto
vale
como podemos ver
ahora no me ha dado
el error
no me ha dado
ningún error
y me ha añadido
aquí la personita
bueno el teléfono
que le he puesto
ha sido un poco
pero
ahora sí
que me ha añadido
la persona
a ver
podríamos cambiar
el tema
el login form
este que es un poco
feo
podríamos poner
el
set is locked
set is locked
y vamos a decir
que por defecto
debería ser false
pero bueno
esto en realidad
no es exactamente
false
sino que esto
debería haber
el local storage
get item
no sé qué
deberíamos ver esto
que esto
ya vimos en
en la clase
de custom hooks
como lo podrías hacer
mucho mejor
pero bueno
vamos a hacer esto
si es lock
y aquí lo que
podríamos hacer
es justamente
añadirle algún tema
para
para borrar el token
así que
vamos a hacer eso
vamos a hacer eso
además aquí también
este null
esto
podríamos hacer
exactamente lo mismo
que de hecho
estoy pensando
que este local storage
y todo
esto
también lo podríamos sacar
de otra forma
y eso
mira
vamos a poner esto
local storage
token
set token
esto en lugar
de hacerlo aquí
lo vamos a hacer
en otro sitio
vamos a hacer
en la app
de forma que
cuando tengamos
el token
si tenemos
un token
pues que no
token
no tenemos token
y
esto
de forma que
si tenemos token
pues no nos aparezca
el formulario de login
porque si no
es un poco rollo
¿no?
de tener que iniciarse
todo el rato
y ahora si elimino
el local storage
y me voy aquí
pues ahora sí que me aparece
si me vuelvo a loguear
bueno
ground credentials
porque
vete a saber
qué contrasean
me guardo aquí
midu password
login
¿vale?
ha desaparecido
y ya estaría
esto al menos
para que no aparezca
ahí cada dos por tres
lo interesante de esto
es
que cuando
yo ahora
pues añado a una persona
a Pepito
Pepito
con phone
12345
de
la calle
Montserrat
y de Barcelona
debería aparecer ahí
¿vale?
Pepito
ha aparecido
sin problemas
y he podido hacer
justamente esto
porque le estoy enviando
la cabecera
en cada una
de las peticiones
ahora ya le estoy enviando
el token
sin ningún tipo
de problema
un problema
que te puedes encontrar
aquí
claro
pongamos que el usuario
por lo que sea
quiere cerrar sesión
pero cuando
cierra
cuando has cerrado
la sesión
o sea
cuando el usuario
cierra sesión
la caché
de Apolo
se queda ahí
¿vale?
la caché
se ha quedado ahí
como en pajaritos
para limpiar la caché
hay que limpiar la caché
¿vale?
hay que limpiar la caché
porque si no
te puedes encontrar
un montón de problemas
de que tú
cierras la sesión
la caché
se mantiene ahí
y puede no funcionar
correctamente
¿qué le pasa a esto?
fíjate
¿qué ha pasado?
mira
ahí
está como partido
eso
bueno
entonces tenemos
que limpiar
la caché
cada vez que el usuario
cierre la sesión
cuando el usuario diga
bueno
hasta aquí
pues entonces
tenemos que hacer
alguna forma
de que
de que se limpie todo
vamos a hacer
esto para limpiarlo
para limpiarlo
una cosa que podríamos
hacer aquí
es recuperar
el cliente de Apolo
con client
podríamos hacer
use apolo client
con el hook
de apolo client
veis que me lo ha
importado de aquí
directamente
y ahora
podríamos crear
una
un logout
aquí
que sea una función
que haga
primero
va a limpiar el token
segundo
va a limpiar
el local storage
y tercero
va a
resetear
¿vale?
del client de Apolo
va a resetear
la store
porque si no
es lo que te digo
tú como usuario
registrado
has iniciado la sesión
Apolo ha empezado
a cachear un montón
de cosas
cierra la sesión
y de repente
te puedes encontrar
que hay un montón
de queries
de información
que no deberías tener
o cosas así
pero claro
es que Apolo
es incapaz
de saber
que debe dejar
de enseñarte
esos datos
entonces
lo mejor
que puedes hacer
es cuando vayas
a hacer
el usuario
cierra la sesión
bueno aparte del token
que lo estamos limpiando
el local storage
que lo estamos limpiando
y tal
y el reset store
porque es que si no
ya te digo
que puedes tener problemas
así que ahora
si no tenemos token
pues enseñamos
el login form
y bueno
podemos hacerlo al revés
mejor
me gustan más
cuando las ternarias
siempre el positivo
lo primero
así que hacemos
button on click
y un logout
cerrar sesión
y si no
pues hacemos esto
vale
si tenemos token
enseñamos el botón
si no
enseñamos el
login form
vamos a ver si esto
tu tu tu tu tu
client
ay
que he puesto client
dos veces aquí
a ver client
ay
fíjate
porque
use person
esto es que lo expliqué
que era una mala práctica
vale
que un custom hook
exporte
la implementación
era como mala práctica
a no ser que sea
un custom hook
que es de un tercero
entonces
que no era buena idea
que el use persons
tenga justamente
esto del client
de hecho
como ya expliqué
la clase anterior
aunque es que
si hiciese esto
en cada una de las clases
estaría aquí todo el día
todo esto que hemos hecho
del use apollo client
todo el tema del login
esto lo vimos en la clase
de custom hooks
por favor
no dejes
en tus componentes
este tipo de
este tipo de lógica
¿por qué?
porque
esto lo puedes
extraer muy fácilmente
en un custom hook
lo hemos visto
en diferentes
diferentes clases
de hecho en la anterior
veis
hicimos el use persons
para que no tengas que ver
tú el use apollo client
lo que tendrías que tener
es extraer
a un custom hook
y decir
en lugar de
un use apollo client
a lo mejor es
un
podría ser
logout
use user
y al hacer el logout
ejecutar a lo mejor
todo esto
pero tú
en los componentes
no tener que ver
nada sobre apollo
¿vale?
o sea
es súper importante
y podrías tener
el token guardado
podrías tener
un montón de cosas
entonces
con esto
ahora
tendríamos
el tema
de limpiar la caché
tendríamos la cerrada
la sesión
si mirásemos
no sé si tengo
por aquí la caché
la caché
¿vale?
tengo aquí personas
no sé qué
al cerrar la sesión
¿veis?
no caché de eta
¿vale?
se ha borrado
totalmente la caché
de esta forma
hombre
pues es bastante
ahora empieza de nuevo
a guardar temas
en la caché
¿por qué?
porque si es que
si no en la caché
a lo mejor tú
como usuario registrado
tienes más información
de las personas
te aparece ahí
bueno
solo que te acuerdes
¿ok?
que tienes que hacer esto
para no
para no mezclarlo
porque es que si no
yo he visto un montón
de problemas con esto
y a veces
en algunas aplicaciones
que utilizan Apolo
y que son bastante conocidas
lo hacen
y sería
sería parda
una última cosa
que además
me lo preguntaste
es la semana anterior
sobre el tema
de actualizar la caché
sin hacer el refresh
ay que rica
la cerveza
a ver
voy a leer un momento
a ver que comentáis
¿hay servidor de Discord?
sí
discord.gg
barra
mi dude
y si no
comando
exclamación
discord
el notify error
hecho con tiempo
sería un use callback
para evitar
re-renders
vamos a ver
ay
he puesto ahí
el blog de notas
notify error
sí
sí totalmente
a ver
sí
y no
a ver
sí
lo que pasa
es que hay veces
que
hay que tener en cuenta
que
es mejor
saber
qué es lo que
cuál es el problema
que estás optimizando
antes de hacer una optimización
prematura
porque el use callback
puede tener
su coste
per se
que a lo mejor
el problema
no es tanto
notify error
yo lo que te diría
es de utilizar
el use callback
cuando realmente
es necesario
ver
si el notify error
ha cambiado
como dependencia
o lo mismo
pasaría un poco
o el use memo
sí que puede tener
más sentido
cuando el cálculo
es muy grande
pero no
soy muy fan
de añadir
muchos use callbacks
indiscriminadamente
optimizaciones
prematuras
normalmente
luego
lo que da
es más problemas
que otra cosa
si el notify error
realmente detectas
que es un problema
que te está dando
el tema de rendimiento
o que está causando
que se empiecen
a renderizar cosas
sin necesidad
pues entonces sí
pero yo evitaría
hacerlo de primeras
así ahora ya
pam
toma
use callback
eso es lo que me parece a mí
eso creo yo
eh
ta ta ta
vale
venga pues
el tema de actualizar
la caché
que ya más o menos
he leído
que no había nada
imaginad
que tenemos que actualizar
la caché
de hecho lo estábamos haciendo
en el person form
bueno no estamos actualizando
la caché
sino lo que pasa aquí
en el person form
es que cuando tú añades
que lo acabamos de ver
¿no?
yo he añadido
cuando estaba aquí
iniciado sesión
otra vez con el gron
que dencia
mi password
sí
guarda nueva contraseña
que me tiene ya frito
vale
cuando añadimos
una nueva persona aquí
podemos ver que
por ejemplo
vamos a añadir
a yaul
yaul
y el teléfono
cuando yo añado
la persona
podemos ver aquí
que se va a añadir
¿vale?
pero fíjate
como hace esto
yo le doy a añadir
ah
vale
ha fallado
porque yaul
solo tiene
cuatro letras
y hemos puesto
una validación
de que fuesen cinco
vamos a poner
gorusuke
gorusuke
no
gorusuke
con el teléfono
444444
la calle
Twitch
y la ciudad
javascript
¿vale?
voy a añadir
esta persona
¿vale?
me ha dejado fatal
porque no me ha aparecido
y no sé por qué
antes me ha aparecido
ay
no será porque
hemos añadido
porque hemos visto
bueno
no sé por qué
a ver
pero antes me lo ha añadido
¿eh?
no sé por qué
ahora se le ha ido
vale
o sea que
no sé
a lo mejor he hecho algo ahí
cuando estaba cambiando
el tema de la cacha
y todo esto
el tema
¿veis que ha aparecido
automáticamente?
pero si miramos
la network
podríamos ver
que ha hecho un fetch
para poder
enseñar eso
¿vale?
para poder enseñar eso
lo que ha hecho
es un refetch
porque en nuestro código
si nos fijamos
en el person form
yo hice esto
que cada vez
que se creaba
una persona
hiciese un refetch
de la query
all persons
y de esta forma
está ocurriendo
esa sincronización
esto está bastante bien
el problema
es que
cada vez que creamos
una persona
ocurre esto
y si por lo que fuese
editásemos
bueno
editar el phone number
no
pero
si
de algún modo
cada vez que creamos
una persona
tenga que hacer
este refetch
es un poco innecesario
¿por qué?
porque ya tenemos
toda la información
de esa persona
y lo podríamos añadir
manualmente nosotros
a la cache
así que
en lugar de utilizar
el refetch queries
este que tenemos aquí
lo que podemos hacer aquí
es utilizar
el update
el update
lo que nos permite
es recuperar
la store
que la store
es donde se está guardando
toda la cache
y aquí tendríamos
también la respuesta
la response
al final
lo que tendría
es la respuesta
de la mutación
la respuesta
que hemos recibido
al hacer la mutación
y justamente
la respuesta
a la mutación
es la que tiene
toda la información
del usuario
así que si hemos hecho
que esta mutación
nos devuelva
este create person
nos devuelva
toda la información
necesaria
que ya vemos aquí
que sí
tenemos el nombre
el teléfono
la dirección
tenemos toda la información
que necesitamos
no hace falta
volver a hacer
un refetch
sobre esto
así que
en el update
que tenemos aquí
la store
la response
esto es un método
lo que vamos a hacer
es recuperar
la información
que tenemos
en la store
hacemos un read query
que esto sí que lo vimos
en la clase anterior
de la query
all persons
¿vale?
para poder recuperar
la información
de la store
tenemos que decirle
qué query es
de la que queremos
extraer la información
porque así es como
se guarda la store
¿vale?
a través de las queries
y ahora lo podemos decir
vale
ahora que tengo
el data en store
quiero que me grabes
en la store
me escribas
en la query
y le tenemos que decir
la query
la que tienes que escribir
all persons
quiero que me escribas
la siguiente información
la información
que ya teníamos
en el data en store
y además
en all persons
quiero
que me grabes
también
esto es lo típico
de cómo actualizar
un array
o un objeto
anidado
y todo esto
en all persons
quiero que me guardes
lo que hay
en data en store
punto
all persons
y además
añadas a otra persona más
que es la que acabo de crear
que viene en response
punto data
punto
add person
¿vale?
¿cómo funciona esto?
lo reviso
¿vale?
una vez más
a ver
esto puede tener
sentido
esto puede tener sentido
sobre todo
cuando necesitas
que la caché
se mantenga actualizada
y no quieres
que haga
la query después
ya sea porque
la query después
tarda mucho
porque
es una optimización
que quieres hacer
porque
no sé
o sea
ten en cuenta
que el refresh query
suele ser
también buena opción
¿ok?
esto sería una forma
de hacerlo
si quieres evitarte
el refresh
pero a veces
el refresh
es necesario
porque a lo mejor
hay información
que la mutación
no te da
o no
o no es capaz
de calcularla
lo que sea
¿vale?
entonces con el update
lo que puedes hacer
es actualizar
tú manualmente
la caché
y tendrías
un parámetro store
que es donde tienes
toda la caché
de todas las queries
y response
que sea la respuesta
de la mutación
recuperaríamos
toda la información
que tenemos
en la store
sobre la query
all persons
que es justamente
donde queremos
actualizar
y lo que haríamos
es escribir
en esa query
en la de all persons
la información
que ya tenía
y en la propiedad
all persons
que era un array
todos los all persons
que ya tenía
y además
el que estamos
añadiendo
de la mutación
esto va a evitar
que haga
un refresh
porque nosotros
estamos manualmente
añadiendo esto
a la caché
ten cuidado
con esto
¿vale?
un gran poder
conlleva una gran
responsabilidad
y si tú
actualizas mal
la caché
y lo haces manualmente
hacerlo manualmente
es bastante rollo
y si lo haces mal
la puedes liar
mucho
¿ok?
así que
tenlo con cuidado
porque mantener
la caché
sobre todo
cuando la aplicación
es muy grande
es un desafío
importante
¿vale?
ahora que hemos
hecho esto
ahora que hemos
hecho esto
voy a refrescar
para asegurarme
que tengo
los cambios
¿vale?
vamos a ver
si esto funciona
porque yo lo he hecho
ahí
pero
vamos a poner
aquí
vamos a poner
algún nombre
de alguien
Imanolde
que dice
que esto ha sido
Imanolde
con teléfono
bla bla bla
y la calle
Midu Midu
y en la ciudad
Twitch
¿vale?
vamos a darle
add person
vale
fíjate
que ahora
ha añadido
a Imanolde aquí
y claro
ha hecho
una petición
pero la petición
que ha hecho
es la de la mutación
¿vale?
¿ves?
es la petición
del add person
pero no ha hecho
ninguna otra
esta que está haciendo aquí
esto es un pre-flight
esto no está haciendo
absolutamente nada
esta es la de options
pero no
no ha hecho
no ha añadido nada
de hecho esta va arriba
no sé por qué la enseña abajo
pero primero ha hecho esta
y luego ha hecho la de arriba
de hecho no sé
debería estar
no sé por qué salen al revés
o salían al revés
pero así era la correcta
ahora no estamos haciendo un refetch
¿ok?
no hemos quitado el refetch
y lo que hemos hecho
lo que hemos hecho
es nosotros actualizar
manualmente
la caché
¿ok?
esto es una forma de optimizar
bastante
nuestra
nuestra forma de actualizar
los datos de la aplicación
y de la caché
como puedes ver
lo que estamos haciendo
es tener un estado global
que estamos manteniendo
nosotros mismos
y que funciona genial
porque se ha visto
reflejado en la UI
pero ten en cuenta eso
que gran poder
conlleva una gran responsabilidad
¿cómo se podría liar
mucho con la caché?
verax
imagínate
o sea
imagínate que yo
es muy fácil
imagínate
yo estoy aquí
y digo
venga
pues ahora en data
voy a poner
que el old person
esto es
false
yo que sé
imagínate false
porque es un caso extremo
pero como se puede liar
es que tú
lo que pones aquí
lo que pongas aquí
no tenga sentido
con los datos
¿vale?
aquí no hay ningún control
de datos
si yo aquí
me pongo a poner false
pues ya esto
cuando se intente
poner la UI
pues vamos a ver
qué pasa
pero seguramente
nada bueno
nada bueno
nada bueno
ah pues mira
igual se la comió
con patatas
old person
false
pensaba
mira mira
caché
mira
hay aquí un error
tu address
this problem
no sé qué
no sé cuánto
¿ves?
o sea
además
aquí hay algo
different custom
merge function
no sé qué
o sea
pensaba que
no lo veríamos
no sé si
a lo mejor
ha hecho
igualmente un fetch
o si ha pasado
directamente
de mí
¿ves?
ha hecho
ha hecho un fetch
ha hecho un fetch
de old persons
ha hecho un refetch
básicamente
pues mira
al menos
al menos
pero
esto es en el caso
de hacerlo muy bestia
¿no?
porque he puesto un false
pero imagínate
que la información
que pones de add person
aquí
sea incorrecta
¿sabes?
en lugar de poner
pepito
o sea
el nombre que espera
pones otro
pues
al final
es el hecho de decir
que la información
que puedes estar mostrando
es incorrecta
vale
muy bien
bueno pues nada
que nos vamos
vamos
vamos
a
vamos
vamos
to