Type variants
Multiple GraphQL types backed by the same contract model
Use variant to expose the same Prisma model as another GraphQL type. For example, a Viewer
type can show signed-in users their own email and drafts, which the public User type leaves out:
const Viewer = builder.prismaObject('User', {
variant: 'Viewer',
fields: (t) => ({
id: t.exposeID('id'),
email: t.exposeString('email'),
drafts: t.relation('posts', { query: { where: { published: 0 } } }),
}),
});Return a variant
Wherever you use the model name, such as 'User', you get the default type. To return the variant,
pass its ref as type, for example from a root field:
builder.queryFields((t) => ({
viewer: t.prismaField({
type: Viewer,
nullable: true,
query: (_args, ctx) => ({ where: { id: ctx.userId } }),
}),
}));t.relation takes a variant's ref as type the same way.
Switch to another variant
t.variant adds a field that returns the same row as another variant, without another query. To
return null for some rows, pass isNull, which needs a nullable field. It sees the primary key,
the type's select, and the columns in the field's select. Here User.viewer returns the
Viewer type only for the signed-in user:
builder.prismaObject('User', {
fields: (t) => ({
viewer: t.variant(Viewer, {
nullable: true,
isNull: (user, _args, ctx) => user.id !== ctx.userId,
}),
}),
});Adding fields
To add fields to a variant, pass its ref to prismaObjectField or prismaObjectFields:
builder.prismaObjectField(Viewer, 'displayName', (t) =>
t.string({
select: { firstName: true, lastName: true },
resolve: (user) => `${user.firstName} ${user.lastName}`,
}),
);To return either User or Viewer from one field, give them a shared
GraphQL interface.