You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesi贸n a prueba de IA

Antes: $249

Currency
$209
Suscr铆bete

Termina en:

0 D铆as
22 Hrs
53 Min
7 Seg

Custom Scalars

21/24
Resources

Link of interest:

GraphQL Scalars

Contributions 7

Questions 1

Sort by:

Want to see more contributions, questions and answers from the community?

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.

Custom Scalars

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.

Scalars Personalizados

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;

Crear scalar personalizado con Expresiones regulares

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

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:

  • Int: A signed 32-bit integer.
  • Float: A signed double-precision floating-point value.
  • String: A UTF-8 character sequence.
  • Boolean: Represents a boolean value of true or false.
  • ID: Represents a unique identifier, often serialized as a string.

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.

npm graphql-scalars

It鈥檚 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:

  • Date: Represents a date value.
  • DateTime: Represents a date and time value.
  • Time: Represents a time value.
  • EmailAddress: Represents an email address value.
  • URL: Represents a URL value.
  • JSON: Represents a JSON object value.
  • PhoneNumber: Represents a phone number value.
  • BigInt: Represents an arbitrary precision integer value.
  • GUID: Represents a globally unique identifier value.

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.

Custom scalar type

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
**CUSTOM SCALARS** *En* **GraphQL***, los **scalars** **personalizados** son **tipos** de **datos** **escalares** **definidos** por el **usuario** que permiten **representar** **datos** **espec铆ficos** de manera m谩s **sem谩ntica** y **precisa** en un **esquema*** **GraphQL***. **Aunque** la **especificaci贸n** de* **GraphQL** ***incluye** **tipos** **escalares** **predeterminados** como* **Int***,* **Float***,* **String***,* **Boolean** *y* **ID***, a **menudo** es **necesario** **admitir** **tipos** de **datos** **at贸micos** **personalizados*** (como Fecha, email) *o **crear** **versiones** **personalizadas** de **tipos** **existentes** que **realicen** **validaciones** **adicionales**. Los **scalars** **personalizados** permiten esta **flexibilidad** al permitir a los **desarrolladores** **definir** sus **propios** **tipos** **escalares** para **adaptarse** a las **necesidades** **espec铆ficas** de sus **aplicaciones**. A **diferencia** de las **enumeraciones**, que **limitan** sus **valores** a una **lista** **predefinida** de **cadenas**, los **scalars** **personalizados** pueden **representar** una **variedad** m谩s **amplia** de **datos** **at贸micos** con **validaciones** **personalizadas**.*

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