GQLoom

Yup

Yup is a schema builder for runtime value parsing and validation. Define a schema, transform a value to match, assert the shape of an existing value, or both. Yup schema are extremely expressive and allow modeling complex, interdependent validations, or value transformation.

@gqloom/yup provides integration of GQLoom with Yup to weave Yup Schema into GraphQL Schema.

Installation

npm i @gqloom/core yup @gqloom/yup

Also, we need to declare metadata from GQLoom for Yup in the project:

yup.d.ts
import 'yup'
import { type GQLoomMetadata } from "@gqloom/yup"
 
declare module "yup" {
  export interface CustomSchemaMetadata extends GQLoomMetadata {}
}

Defining simple scalars

Yup Schema can be used as a silk in GQLoom using yupSilk:

import { , ,  } from "yup"
import {  } from "@gqloom/yup"
 
const  = (())
 
const  = (())
 
const  = (())
 
const  = (().())

Defining objects

We can use Yup to define objects and use them as silk to use:

import { , , ,  } from "yup"
 
export const  = ({
  : ().(),
  : ().().(),
  : (),
}).("Cat")

Names and more metadata

Defining names for objects

Using label()

import { , , ,  } from "yup"
 
export const  = ({
  : ().(),
  : ().().(),
  : (),
}).("Cat")

In the above code, we have defined the name for the object using label so that the object will have the name Cat in the generated GraphQL Schema.

Using collectNames

import { , , ,  } from "yup"
import {  } from "@gqloom/yup"
 
export const  = ({
  : ().(),
  : ().().(),
  : (),
})
 
({  })

In the above code, we are using the collectNames function to define names for objects. The collectNames function accepts an object whose key is the name of the object and whose value is the object itself.

import { , , ,  } from "yup"
import {  } from "@gqloom/yup"
 
export const {  } = ({
  : ({
    : ().(),
    : ().().(),
    : (),
  }),
})

In the code above, we use the collectNames function to define the names for the objects and deconstruct the returned objects into Cat and export them.

Using asObjectType metadata

import { , , ,  } from "yup"
 
export const  = ({
  : ().(),
  : ().().(),
  : (),
}).({ : { : "Cat" } })

In the above code, we have used meta function in Yup Schema to define the name for the object. Here, we have defined the name asObjectType metadata and set it to { name: “Cat” } so that in the generated GraphQL Schema, the object will have the name Cat.

Add more metadata

We can use the meta function in Yup Schema to add more metadata, such as description, deprecationReason, extensions and so on.

import { , , ,  } from "yup"
 
export const  = ({
  : ().(),
  : ().().(),
  : (),
}).({ : { : "Cat", : "A cute cat" } })

In the above code, we have added description metadata to the Cat object so that in the generated GraphQL Schema, the object will have the description A cute cat:

GraphQL Schema
"""A cute cat"""
type Cat {
  name: String!
  age: Int!
  loveFish: Boolean
}

We can also use the asField attribute in the metadata to add metadata to the field, such as description, type, and so on:

import { , , ,  } from "yup"
import {  } from "graphql"
 
export const  = ({
  : ().(),
  : ().({
    : { : () => , : "How old is the cat" },
  }),
  : (),
}).({ : { : "Cat", : "A cute cat" } })

In the above code, we added type and description metadata to the age field and ended up with the following GraphQL Schema:

GraphQL Schema
"""A cute cat"""
type Cat {
  name: String!
 
  """How old is the cat"""
  age: Int
  loveFish: Boolean
}

Declaring Interfaces

We can also use the asObjectType function to declare interfaces, for example:

import { , ,  } from "yup"
 
const  = ({
  : ().(),
  : ().(),
  : ()
    .()
    .({ : "How much do you want to win?" }),
})
  .({ : "Fruit Interface" })
  .("Fruit")
 
const  = ({
  : ().(),
  : ().(),
  : ().(),
})
  .({ : { : [] } })
  .("Orange")

In the code above, we declared the Orange object as an implementation of the Fruit interface using the interfaces attribute in asObjectType.

Omitting fields

We can also omit fields by setting the type to null using the asField attribute, for example:

import { , , ,  } from "yup"
 
export const  = ({
  : ().(),
  : ()
    .()
    .({ : { : null } }),
}).({ : { : "Cat", : "A cute cat" } })

The following GraphQL Schema will be generated:

GraphQL Schema
type Dog {
  name: String
}

Defining Union Types

Use union from @gqloom/yup to define union types, for example:

import { object, string, number } from "yup"
import { union } from "@gqloom/yup"
 
const Cat = object({
  name: string(). required(),
  color: string().required(),
}).label("Cat")
 
const Dog = object({
  name: string().required(),
  height: number().required(),
}).label("Dog")
 
const Animal = union([Cat, Dog]).label("Animal")

In the above code, we used the union function to define the Cat and Dog objects as members of the Animal union type.

Defining enumerated types

Using oneof()

We can use string().oneof() to define enumerated types, for example:

import {  } from "yup"
 
const  = ()
  .(["apple", "banana", "orange"])
  .("Fruit")
  .({
    : {
      : "Some fruits you might like",
      : {
        : { : "Apple is red" },
        : { : "Banana is yellow" },
        : { : "Orange is orange" },
      },
    },
  })

Using enum

We can also use enum to define enumeration types, for example:

import {  } from "yup"
 
enum  {
  ,
  ,
  ,
}
 
const  = ()
  .(.() as [])
  .("Fruit")
  .({
    : {
      : ,
      : "Some fruits you might like",
      : {
        : { : "Apple is red" },
        : { : "Banana is yellow" },
        : { : "Orange is orange" },
      },
    },
  })

Custom Type Mappings

To accommodate more Yup types, we can extend GQLoom to add more type mappings to it.

First we use YupWeaver.config to define the type mapping configuration. Here we import GraphQLDateTime from graphql-scalars, and when we encounter a date type, we map it to the matching GraphQL scalar.

import {  } from "graphql-scalars"
import {  } from "@gqloom/yup"
 
export const  = .({
  : () => {
    switch (.) {
      case "date":
        return 
    }
  },
})

Configurations are passed into the weave function when weaving the GraphQL Schema:

import {  } from "@gqloom/yup"
 
export const  = (, )

Default Type Mappings

The following table lists the default mappings between Yup types and GraphQL types in GQLoom:

Yup typesGraphQL types
string()GraphQLString
number()GraphQLFloat
number().integer()GraphQLInt
boolean()GraphQLBoolean
object()GraphQLObjectType
array()GraphQLList
union()GraphQLUnionType
string().oneof(["Value1"])GraphQLEnumType