Prisma Objects
Prisma plugin docs for Pothos
Creating types with builder.prismaObject
builder.prismaObject takes 2 arguments:
name: The name of the prisma model this new type representsoptions: options for the type being created, this is very similar to the options for any other object type
builder.prismaObject('User', {
// Optional name for the object, defaults to the name of the prisma model
name: 'PostAuthor',
fields: (t) => ({
id: t.exposeID('id'),
email: t.exposeString('email'),
}),
});
builder.prismaObject('Post', {
fields: (t) => ({
id: t.exposeID('id'),
title: t.exposeString('title'),
}),
});So far, this is just creating some simple object types. They work just like any other object type in Pothos. The main advantage of this is that we get the type information without using object refs, or needing imports from prisma client.
Adding prisma fields to non-prisma objects (including Query and Mutation)
t.prismaField defines fields that return Prisma objects. This example uses the client and
userId context from Setup:
builder.queryType({
fields: (t) => ({
me: t.prismaField({
type: 'User',
resolve: async (query, root, args, ctx, info) => {
return prisma.user.findUniqueOrThrow({
...query,
where: { id: ctx.userId },
});
},
}),
}),
});This method works just like the normal t.field method with a couple of differences:
- The
typeoption must contain the name of the prisma model (eg.Useror[User]for a list field). - The
resolvefunction has a new first argumentquerywhich should be spread into your prisma query. This will be used to load data for nested relationships.
You do not need to use this method, and the builder.prismaObject method returns an object ref that
can be used like any other object ref (with t.field), but using t.prismaField will allow you to
take advantage of more efficient queries.
The query object will contain an object with include or select options to pre-load data needed
to resolve nested parts of the current query. The included/selected fields are based on which fields
are being queried, and the options provided when defining those fields and types.
prismaFieldWithInput
With the with-input plugin,
t.prismaFieldWithInput combines t.prismaField with t.fieldWithInput. The input fields become
an input object argument, and the resolver still receives the query to spread as its first
argument.
builder.mutationType({
fields: (t) => ({
createPost: t.prismaFieldWithInput({
type: 'Post',
input: {
title: t.input.string({ required: true }),
authorId: t.input.id({ required: true }),
},
resolve: (query, root, args, ctx) => {
return prisma.post.create({
...query,
data: {
title: args.input.title,
authorId: Number.parseInt(args.input.authorId, 10),
},
});
},
}),
}),
});Extending prisma objects
The normal builder.objectField(s) methods can be used to extend prisma objects, but do not support
using selections, or exposing fields not in the default selection. To use these features, you can
use
builder.prismaObjectField or builder.prismaObjectFields instead.
A nullable author lookup
An author page should return null when the requested author does not exist. A t.prismaField
passes the requested selections into findUnique; its GraphQL nullability matches that method's
result. This field uses the publishing schema described in Setup:
builder.queryType({
fields: (t) => ({
author: t.prismaField({
type: 'User',
nullable: true,
args: { id: t.arg.int({ required: true }) },
resolve: (query, _root, args) => {
return prisma.user.findUnique({
...query,
where: { id: args.id },
});
},
}),
}),
});author(id: 1) { name } returns Maya Chen. author(id: 999) { name } returns null.
The type's relations can be requested through the same field without changing the resolver.