Genial curso!, la verdad muy util las herramientas que brinda el profe a lo largo del curso.
Introducción
¿Qué es GraphQL?
Proyecto: tienda online con GraphQL
Análisis de la API REST (sin GraphQL)
Fundamentos de GraphQL
Tu primera API GraphQL
GraphQL desde Insomnia y Postman
Tipado en GraphQL
Sistema de tipado
Scalar types
Listas y non-null types
Object types and fields
Archivos .graphql (mejor developer experience)
GraphQL en la Tienda con Express.js
Product resolvers
Conectado a ProductService
Mutations and Inputs
Variables y alias
Update and Delete
Anidamiento
Autenticación con GraphQL y JSON Web Tokens
Login
Crear categorÃa
GraphQL con JWT
Validar roles
Custom Scalars
Bonus
Anidamiento dinámico
Conclusiones
GraphQL vs. API REST
Toma el Curso Avanzado de Node.js con GraphQL
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
No se trata de lo que quieres comprar, sino de quién quieres ser. Invierte en tu educación con el precio especial
Antes: $249
Paga en 4 cuotas sin intereses
Termina en:
Nicolas Molina
Aportes 7
Preguntas 1
Genial curso!, la verdad muy util las herramientas que brinda el profe a lo largo del curso.
Excelente, esto hace mucho mas maleable el trabajo con grphql.
En nuestro servidor REST API realizamos validaciones precisas de datos utilizando la librerÃa Joi, pero ¿Cómo lo podemos hacer en consultas GraphQL? Para lograr esto, utilizaremos una técnica llamada custom scalars.
Para utilizar estos tipos de datos, debemos extender GraphQL instalando la librerÃa graphql-scalars
:
npm install graphql-scalars
Esta librerÃa nos permite realizar validaciones nativas en GraphQL, sin necesidad de utilizar librerÃas adicionales como Joi.
Para implementar nuestros scalars, debemos realizar los siguientes pasos en el archivo index.js
de la carpeta graphql
:
const { ApolloServer } = require('apollo-server-express');
const { expressMiddleware } = require('apollo-server-express');
const { loadFiles } = require('@graphql-tools/load-files');
const { buildContext } = require('graphql-passport');
const resolvers = require('./resolvers');
const { typeDefs: scalarsTypeDefs, resolvers: scalarsResolvers } = require('graphql-scalars');
const useGraphql = async (app) => {
// Cargamos los tipos de definición en una única variable dentro de un array
const typeDefs = [
...await loadFiles('./src/**/*.graphql'),
scalarsTypeDefs
];
// Agregamos los resolvers en una única variable dentro de un array
const allResolvers = [
resolvers,
scalarsResolvers
];
// Los implementamos en nuestro servidor Apollo
const server = new ApolloServer({
typeDefs,
resolvers: allResolvers,
});
await server.start();
app.use(
'/graphql',
expressMiddleware(server, {
context: async ({ req, res }) => buildContext({ req, res })
}),
);
};
module.exports = useGraphql;
Luego, podemos comenzar a utilizar los custom scalars en nuestro esquema GraphQL. Aquà hay un ejemplo de cómo se verÃa en nuestro archivo schema.graphql
:
# Tipos de respuesta enviadas
type Mutation {
# login
login(email: EmailAddress! password: String!): AuthResponse
}
# Esquemas de respuestas
type Product {
id: ID!
name: String!
price: Float!
description: URL!
image: String!
createdAt: Date!
categoryId: ID!
category: Category!
}
type Category {
id: ID!
name: String!
image: String!
}
type User {
id: ID!
email: EmailAddress!
role: String!
createdAt: Date!
}
# Esquemas de autenticación
type AuthResponse {
access_token: String!
user: User!
}
# Inputs
# Products
input CreateProductDto {
name: String!
price: Int!
description: String!
image: URL!
categoryId: ID!
}
input UpdateProductDto {
name: String
price: Int
description: String
image: URL
categoryId: ID
}
# Categories
input CreateCategoryDto {
name: String!
image: URL!
}
Excelente, pero ¿Qué sucede si necesitamos realizar una validación adicional, como limitar la longitud de caracteres de un campo? Para esto, podemos utilizar expresiones regulares.
En nuestro archivo resolver.js
, podemos hacer lo siguiente:
const { RegularExpression } = require('graphql-scalars');
// Creamos nuestro nuevo tipo
const CategoryNameType = new RegularExpression('CategoryNameType', /^[a-zA-Z0-9]{3,8}$/);
const resolvers = {
Query: {
// ...
},
Mutation: {
// ...
},
// Para agregarlo, lo agregamos como un nuevo tipo
CategoryNameType
};
module.exports = resolvers;
Luego, debemos realizar un paso adicional en nuestro archivo schema.graphql
:
# Categories
input CreateCategoryDto {
# Y ahora podemos usarlo normalmente
name: CategoryNameType!
image: URL!
}
# Debemos importarlo de la siguiente manera
scalar CategoryNameType
¡Listo! De esta manera, podemos crear tipos de datos complejos utilizando custom scalars en GraphQL.
add resolver and typedef of library
const {ApolloServer}= require('apollo-server-express');
const {ApolloServerPluginLandingPageLocalDefault} = require('apollo-server-core');
const {loadFiles} = require('@graphql-tools/load-files')
const {typeDefs: typeDefsScalars,resolvers:resolversScalars}= require('graphql-scalars');
const {buildContext}= require('graphql-passport')
const resolversApp = require('./resolvers')
// el ! significa un campo obligatorio
const useGraphql= async (app)=>{
const resolvers = [ resolversApp , resolversScalars];
const typeDefs = [ ...await loadFiles('./src/**/*.graphql')/*typesDefs Locals*/ ,typeDefsScalars]
const server = new ApolloServer({
typeDefs,
resolvers,
context:({req,res})=> buildContext({req,res}),
plugins: [ApolloServerPluginLandingPageLocalDefault]
});
await server.start();
server.applyMiddleware({app})
}
module.exports = useGraphql;
const { login } = require("./auth/auth.resolver")
const { allCategories, categoryById , addCategory} = require("./categories.resolver")
const { product, products ,createProduct,deleteProduct,updateProduct} = require("./product.resolver")
const { getPersons , findPerson, createPerson} = require("./resolver.person")
const {RegularExpression} = require('graphql-scalars')
// creamos el type con una nueva instancia de RegularExpression
const CategoryNameType= new RegularExpression('CategoryNameType', /^[a-zA-Z0-9]{3,8}$/);
const resolvers= {
Query:{
saludo: ()=> 'hola mundillo de internet',
persons:getPersons,
findPerson,
allCategories,
categoryById,
product,
products
},
Mutation:{
createPerson,
createProduct,
deleteProduct,
updateProduct,
addCategory,
login
},
CategoryNameType // add new type
}
module.exports = resolvers
utilizamos nuestro scalars en nuestros typeDefs
scalar CategoryNameType
input CreateCategory {
name: CategoryNameType!,
image: URL!,
# products:[Product]
}
el type URL retorna es un objecto con la url desustrurada, por lo tanto se debe sacar la url del objeto en la propiedad href
const addCategory = async (root, {dto},context)=>{
const user = await checkJwtGql(context) //validate jtw
checkRoleGql(user,'admin') ; // validate Role
// console.log(dto)
const newCategory = await service.create({
...dto,
image:dto.image.href// url Image
});
return newCategory;
}
GraphQL scalars are predefined scalar types in GraphQL that represent basic data types. Scalars are used to define the shape and type of individual fields in a GraphQL schema. While GraphQL supports custom scalar types, it also provides a set of built-in scalars that cover common data types.
Here are the built-in scalar types in GraphQL:
These scalar types are the building blocks for defining the data types of field values in GraphQL schemas. They are used to specify the expected types of field arguments and return values.
GraphQL also allows you to define custom scalar types if the built-in scalars do not cover your specific data needs. Custom scalars are useful when dealing with specialized data types such as dates, email addresses, URLs, etc. Custom scalars provide a way to enforce validation and parsing rules for these specific types.
Overall, scalars in GraphQL allow you to define and enforce specific data types for the fields in your API, providing a clear contract for data communication between the client and server.
graphql-scalars
It’s a popular npm package that provides a collection of commonly used custom scalar types for GraphQL. It simplifies the process of adding custom scalar types to your GraphQL server by providing pre-defined implementations for various data types.
The graphql-scalars library offers a wide range of custom scalar types that are not available as built-in scalars in GraphQL. Some of the commonly used custom scalar types provided by graphql-scalars include:
Using the graphql-scalars library, you can easily add these custom scalar types to your GraphQL schema by importing them and including them in your type definitions.
We can create a custom scalar type by defining it in the resolvers.
import { RegularExpression } from "graphql-scalars";
// the string can have a-z characters in lower/capital case
// min length: 3, max length: 8
const CategoryNameType = new RegularExpression(
"CategoryNameType",
/^[a-zA-Z-09]{3,8}/
);
See ./graphql/resolvers.ts
Then add it to the resolvers:
export const resolvers = {
Query: {
// ...
},
Mutation: {
// ...
},
// Create new types
CategoryNameType, // <---
};
Finally call it inside the schema.graphql
file
scalar CategoryNameType
hay que tener en cuenta que también debemos cambiar el schema para actualizar una categorÃa
src/graphql/schema.graphql:
input UpdateCategoryDto {
name: String
image: URL
}
y su resolver
src/graphql/category.resolvers.js:
const updateCategory = (_, { id, dto })=> {
return service.update(id, {
...dto,
image: dto.image.href
})
}
esto debido a que si no lo hacemos, podrÃamos modificar la categorÃa pasándole un String cualquiera y seria permitido
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?