const User = builder.prismaObject('User', {
// Used as a fallback when loading relations that are not pre-loaded (explained more later)
findUnique: (user) => ({ id: user.id }),
fields: (t) => ({
id: t.exposeID('id'),
name: t.exposeString('name'),
posts: t.relation('posts', {
args: {
includeDrafts: t.arg.boolean()
},
orderBy: { date: 'desc' }, // can also be function that accepts args
where: (args) => args.includeDrafts ? {} : { draft: false }
}),
}),
});
const Post = builder.prismaObject('Post', {
findUnique: (post) => ({ id: post.id }),
fields: (t) => ({
id: t.exposeID('id'),
title: t.exposeString('title'),
author: t.relation('author'),
}),
});
builder.queryType({
fields: (t) => ({
// first arg is include/select needed for queried relations
me: t.primaField({
type: 'User',
resolve: (query, root, args, ctx, info) => prisma.user.findUnique({
...query,
where: {
id: ctx.user.id,
},
}),
}),
// normal field that doesn't automatically query for relations
post: t.field({
type: Post,
resolve: (root, args, ctx, info) => prisma.post.findUnique({
where: {
id: ctx.user.id,
},
}),
}),
}),
});
query {
me {
id
name
posts {
title
}
}
}
generated query:
prisma.user.findUnique({
include: {
post: {
where: { draft: false }
},
},
where: {
id: ctx.user.id,
},
})
query {
me {
id
posts {
title
author {
name
}
}
}
}
generated query:
prisma.user.findUnique({
include: {
post: {
where: { draft: false },
include: {
author: true,
},
},
},
where: {
id: ctx.user.id,
},
})
query {
me {
id
name
posts {
title
author {
name
}
}
withDrafts: posts(includeDrafts: true ) {
title
author {
name
}
}
}
}
generates 2 queries:
prisma.user.findUnique({
include: {
post: {
where: { draft: false },
include: {
author: true,
},
},
},
where: {
id: ctx.user.id,
},
});
// generated for drafts. The where in this query is derived from the findUinique defined on the object.
// We can't include posts twice, since the posts relation is queried twice, for the second field we use a
// generated findUnique based on the user returned by the first query. This does mean this query won't
// fire until after the other query completes.
prisma.user.findUnique({
include: {
post: {
include: {
author: true,
},
},
},
where: {
id: 123, // id of current user (extracted from first query result)
},
});
query {
post(id: 123) {
title
author {
name
}
}
}
Results in 2 queries, firs the query defined in the field, then the following query for the author:
prisma.post.findUnique({
where: { id: 123 }, // created by findUnique on post type
include: {
author: true,
},
});
I have most of the types working correctly, but need to figure out how this will play with relay and data-loader plugins.