SchemaBuilder
The central builder every Pothos type is defined on, configured through its SchemaTypes generic and constructor options.
Every Pothos schema starts with a SchemaBuilder, and every type in the schema is defined through it. The builder holds two kinds of configuration: a SchemaTypes generic that shapes what TypeScript infers, and a constructor options object that carries runtime settings like the list of plugins.
Creating a builder
import SchemaBuilder from '@pothos/core';
interface Context {
user?: { id: number; name: string };
}
const builder = new SchemaBuilder<{
Context: Context;
Scalars: {
DateTime: { Input: Date; Output: Date };
};
}>({});The generic parameter is an object Pothos calls SchemaTypes. This one fills in two of its entries: Context declares the type of the context object resolvers receive as their third argument (the Context guide covers where that object comes from), and Scalars declares the TypeScript types for a custom DateTime scalar (the Scalars guide covers implementing it). The constructor takes an options object; with no plugins here it stays empty.
You typically create one builder per schema and export it from a shared module, so every file that defines part of the schema imports the same builder. The Project layout pattern shows one way to organize this.
The SchemaTypes generic
The generic is type-level configuration: it changes what TypeScript accepts and infers, and nothing you write in it is passed to the constructor. Every entry is optional; you supply the ones you care about, and Pothos fills in defaults for the rest. Each entry is covered in depth on its own page:
Context: the shape of the per-request context object. Covered in Context.Scalars: the Input/Output TypeScript types for each named scalar. The runtime implementation is registered later withbuilder.scalarType, covered in Scalars.DefaultFieldNullabilityandDefaultInputFieldRequiredness: schema-wide defaults for whether output fields are nullable and input fields are required. Covered in Default nullability.Objects,Interfaces, andInputs: maps from type name to backing model (the TypeScript shape behind a type), which let you reference types by name as strings and keep your type definitions in one place. Object types covers this style alongside the others.- Plugin entries: each installed plugin can add its own entries (
AuthScopesfrom scope-auth,PrismaTypesfrom prisma, and so on), documented on that plugin's page.
Three entries also have a constructor counterpart: Defaults (covered in the v4 migration guide), DefaultFieldNullability, and DefaultInputFieldRequiredness. Setting one of these to a non-default value makes the matching constructor option (defaults, defaultFieldNullability, defaultInputFieldRequiredness) required, and its value has to match. None of the other core entries corresponds to a constructor option. The context value is created by your server for each request, and scalar implementations and named types are registered through builder methods.
Constructor options
The options object holds the runtime configuration. In core, the main option is plugins, the list of plugins the builder should use:
import SchemaBuilder from '@pothos/core';
import RelayPlugin from '@pothos/plugin-relay';
const builder = new SchemaBuilder<{
Context: Context;
}>({
plugins: [RelayPlugin],
});Each installed plugin can also add its own keys to the options object. Some are optional (relay), and some become required as soon as the plugin package is imported (prisma from @pothos/plugin-prisma). The Using plugins guide covers installing and configuring plugins.
Building the schema
export const schema = builder.toSchema();toSchema resolves every type registered on the builder and returns a standard graphql-js GraphQLSchema, so anything that accepts a GraphQLSchema can serve it. Call it after all of your types have been defined, usually at the bottom of the module that imports every type definition.
By default the returned schema is sorted lexicographically; pass toSchema({ sortSchema: false }) to keep definition order instead. toSchema accepts a few other options (directives, extensions), and some plugins add their own build-time options here.