编织 | Weave

在 GQLoom 中,weave 函数用于将多个解析器(Resolver)或丝线(Silk)编织到一张 GraphQL Schema 中。

weave 函数可以接收解析器丝线、编织器配置、全局中间件

编织解析器

最常见的用法是将多个解析器编织到一起,例如:

import { weave } from '@gqloom/core'; export const schema = weave(HelloResolver, CatResolver);

编织单独丝线

有时候,我们需要将一个单独的丝线编织到 GraphQL Schema 中,例如:

valibot
zod
import { resolver, query, field, valibotSilk, weave } from '@gqloom/valibot' import * as v from "valibot" const Dog = v.object({ __typename: v.nullish(v.literal("Dog")), name: v.string(), age: v.number(), }) export const schema = weave(HelloResolver, CatResolver, valibotSilk(Dog));

编织器配置

输入类型命名转换

在 GraphQL 中,对象分为 typeinput 类型。

而使用 GQLoom 时,我们一般只使用 object 类型,在幕后 GQLoom 会自动将 object 类型转换为 input 类型。 这样做的好处是我们可以直接使用 object 类型来定义输入参数,而无需手动定义 input 类型。 但是当我们将同一个 object 类型同时用于 typeinput 时,将因为命名冲突而无法编织成 GraphQL Schema。

让我们来看一个例子:

valibot
zod
import { resolver, mutation, weave } from '@gqloom/valibot' import * as v from "valibot" const Cat = v.object({ __typename: v.nullish(v.literal("Cat")), name: v.string(), birthDate: v.string(), }) const CatResolver = resolver({ createCat: mutation(Cat, { input: { data: Cat, }, resolve: ({ data }) => data, }), }) export const schema = weave(CatResolver);

在上面的代码中,我们定义了一个 Cat 对象,并将其用于 typeinput。但是当我们尝试将 CatResolver 编织到 GraphQL Schema 中时,会抛出一个错误,提示 Cat 名称重复:

Error: Schema must contain uniquely named types but contains multiple types named "Cat".

要解决这个问题,我们需要为 input 类型指定一个不同的名称。我们可以使用 SchemaWeaver.config 配置中的 getInputObjectName 选项来实现这一点:

valibot
zod
import { resolver, mutation, weave, SchemaWeaver } from '@gqloom/valibot' import * as v from "valibot" const Cat = v.object({ __typename: v.nullish(v.literal("Cat")), name: v.string(), birthDate: v.string(), }) const CatResolver = resolver({ createCat: mutation(Cat, { input: { data: Cat, }, resolve: ({ data }) => data, }), }) export const schema = weave( CatResolver, SchemaWeaver.config({ getInputObjectName: (name) => `${name}Input` }) )

如此一来,Cat 对象将被转换为 CatInput 类型,从而避免了命名冲突。

以上的 CatResolver 将编织得到如下 GraphQL Schema:

type Mutation { createCat(data: CatInput!): Cat! } type Cat { name: String! birthDate: String! } input CatInput { name: String! birthDate: String! }

全局中间件

import { weave } from '@gqloom/core'; import { logger } from './middlewares'; export const schema = weave(HelloResolver, CatResolver, logger)

中间件章节中查看更多关于中间件的用法。