GQLoom

Yup

Yup 是一个用于运行时值解析和验证的模式构建器。 您可以定义模式、转换值以匹配、断言现有值的形状,或两者兼而有之。 Yup 模式具有极强的表现力,可对复杂、相互依赖的验证或值转换进行建模。

@gqloom/yup 提供了 GQLoom 与 Yup 的集成,以便将 Yup Schema 编织成 GraphQL Schema。

安装

npm i @gqloom/core yup @gqloom/yup

另外,我们还需要在项目中为 Yup 声明来自 GQLoom 的元数据:

yup.d.ts
import 'yup'
import { type GQLoomMetadata } from "@gqloom/yup"

declare module "yup" {
  export interface CustomSchemaMetadata extends GQLoomMetadata {}
}

定义简单标量

在 GQLoom 中,可以使用 yupSilk 将 Yup Schema 作为丝线使用:

import { , ,  } from "yup"
import {  } from "@gqloom/yup"

const  = (())

const  = (())

const  = (())

const  = (().())

定义对象

我们可以使用 Yup 定义对象,并将其作为丝线使用:

import { , , ,  } from "yup"

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

名称和更多元数据

为对象定义名称

使用 label()

import { , , ,  } from "yup"

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

在上面的代码中,我们使用 label 为对象定义了名称,这样在生成的 GraphQL Schema 中,该对象将具有名称 Cat

使用 collectNames

import { , , ,  } from "yup"
import {  } from "@gqloom/yup"

export const  = ({
  : ().(),
  : ().().(),
  : (),
})

({  })

在上面的代码中,我们使用 collectNames 函数来为对象定义名称。collectNames 函数接受一个对象,该对象的键是对象的名称,值是对象本身。

import { , , ,  } from "yup"
import {  } from "@gqloom/yup"

export const {  } = ({
  : ({
    : ().(),
    : ().().(),
    : (),
  }),
})

在上面的代码中,我们使用 collectNames 函数来为对象定义名称,并将返回的对象解构为 Cat 并导出。

使用 asObjectType 元数据

import { , , ,  } from "yup"

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

在上面的代码中,我们在 Yup Schema 中使用 meta 函数来为对象定义名称。 在这里,我们定义了名称为 asObjectType 元数据,并将其设置为 { name: "Cat" },这样在生成的 GraphQL Schema 中,该对象将具有名称 Cat

添加更多元数据

我们可以在 Yup Schema 中使用 meta 函数来添加更多元数据,例如 descriptiondeprecationReasonextensions 等。

import { , , ,  } from "yup"

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

在上面的代码中,我们为 Cat 对象添加了 description 元数据,这样在生成的 GraphQL Schema 中,该对象将具有描述 A cute cat

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

我们还可以使用元数据中的 asField 属性为字段添加元数据,例如 descriptiontype 等:

import { , , ,  } from "yup"
import {  } from "graphql"

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

在上面的代码中,我们为 age 字段添加了 typedescription 元数据,最终得到如下 GraphQL Schema:

GraphQL Schema
"""A cute cat"""
type Cat {
  name: String!

  """How old is the cat"""
  age: Int
  loveFish: Boolean
}

声明接口

我们还可以使用 asObjectType 函数来声明接口,例如:

import { , ,  } from "yup"

const  = ({
  : ().(),
  : ().(),
  : ()
    .()
    .({ : "How much do you want to win?" }),
})
  .({ : "Fruit Interface" })
  .("Fruit")

const  = ({
  : ().(),
  : ().(),
  : ().(),
})
  .({ : { : [] } })
  .("Orange")

在上面的代码中,我们使用 asObjectType 中的 interfaces 属性将 Orange 对象声明为 Fruit 接口的实现。

省略字段

我们还可以使用 asField 属性将 type 设置为 null 来省略字段,例如:

import { , , ,  } from "yup"

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

将得到如下 GraphQL Schema:

GraphQL Schema
type Dog {
  name: String
}

定义联合类型

使用来自 @gqloom/yupunion 定义联合类型,例如:

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")

在上面的代码中,我们使用 union 函数将 CatDog 对象声明为 Animal 联合类型的成员。

定义枚举类型

使用 oneof()

我们可以使用 string().oneof() 来定义枚举类型,例如:

import {  } from "yup"

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

使用 enum

我们还可以使用 enum 来定义枚举类型,例如:

import {  } from "yup"

enum  {
  ,
  ,
  ,
}

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

自定义类型映射

为了适应更多的 Yup 类型,我们可以拓展 GQLoom 为其添加更多的类型映射。

首先我们使用 YupWeaver.config 来定义类型映射的配置。这里我们导入来自 graphql-scalarsGraphQLDateTime,当遇到 date 类型时,我们将其映射到对应的 GraphQL 标量。

import {  } from "graphql-scalars"
import {  } from "@gqloom/yup"

export const  = .({
  : () => {
    switch (.) {
      case "date":
        return 
    }
  },
})

在编织 GraphQL Schema 时传入配置到 weave 函数中:

import {  } from "@gqloom/yup"

export const  = (, )

默认类型映射

下表列出了 GQLoom 中 Yup 类型与 GraphQL 类型之间的默认映射关系:

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