Weave
In GQLoom, the weave
function is used to weave multiple Resolvers or Silks into a single GraphQL Schema.
The weave
function can take resolver, silk, weaver configuration, global middleware
Weaving resolvers
The most common usage is to weave multiple resolvers together, for example:
import { weave } from '@gqloom/core';
export const schema = weave(HelloResolver, CatResolver);
Weaving a single silk
Sometimes we need to weave a single silk woven into a GraphQL Schema, for example:
import { resolver, query, field, valibotSilk, weave } from '@gqloom/core'
import { ValibotWeaver } 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(ValibotWeaver, HelloResolver, CatResolver, Dog);
Weaver configuration
Input type naming conversion
In GraphQL, objects are recognized as type and input.
When using GQLoom
, we usually only use the object
type, and behind the scenes GQLoom
will automatically convert the object
type to the input
type.
The advantage of this is that we can use the object
type directly to define input parameters without having to define the input
type manually.
However, when we use the same object
type for both type
and input
, it will not be woven into GraphQL Schema due to naming conflict.
Let's look at an example:
import { resolver, mutation, weave } from '@gqloom/core'
import { ValibotWeaver } 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(ValibotWeaver, CatResolver);
In the above code, we defined a Cat
object and used it for type
and input
. But when we try to weave CatResolver
into the GraphQL Schema, an error is thrown with a duplicate Cat
name:
Error: Schema must contain uniquely named types but contains multiple types named "Cat".
To solve this problem, we need to specify a different name for the input
type. We can do this using the getInputObjectName
option in the SchemaWeaver.config
configuration:
import { resolver, mutation, weave, SchemaWeaver } from '@gqloom/core'
import { ValibotWeaver } 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,
ValibotWeaver,
SchemaWeaver.config({ getInputObjectName: (name) => `${name}Input` })
)
Thus, Cat
objects will be converted to CatInput
types, thus avoiding naming conflicts.
The above CatResolver
will weave the following GraphQL Schema:
type Mutation {
createCat(data: CatInput!): Cat!
}
type Cat {
name: String!
birthDate: String!
}
input CatInput {
name: String!
birthDate: String!
}
Global middleware
import { weave } from '@gqloom/core';
import { logger } from './middlewares';
export const schema = weave(HelloResolver, CatResolver, logger)
See more about middleware usage in middleware section.