Relay nodes
Using the Prisma and Relay plugins together
prismaNode adds Relay IDs and root node lookups to Prisma objects. Register the
Relay plugin; see Connections for pagination.
Authorize direct node lookups
Defining a node creates a direct lookup through node and nodes. These lookups bypass custom
root resolvers, so permission checks or visibility filters on a list or parent field do not protect
node refetches. An encoded global ID is an identifier, not proof of permission.
Apply an access policy to node loading, the type, or its fields as appropriate. See Authorizing Relay nodes for scope patterns and their limits.
prismaNode
The prismaNode method works just like the prismaObject method with a couple of small
differences:
- there is a new
idoption that mirrors theidoption fromnodemethod of the relay plugin, and must contain a resolve function that returns the id from an instance of the node. Rather than defining a resolver for the id field, you can set thefieldoption to the name of a unique column or index.
builder.prismaNode('Post', {
// This sets what database field to use for the nodes id field
id: { field: 'id' },
// fields work just like they do for builder.prismaObject
fields: (t) => ({
title: t.exposeString('title'),
author: t.relation('author'),
}),
});If you need to customize how ids are formatted, you can add a resolver for the id, and provide a
findUnique option that can be used to load the node by its id. This is generally not necessary.
builder.prismaNode('Post', {
id: { resolve: (post) => String(post.id) },
// The return value will be passed as the `where` of a `prisma.post.findUnique`
findUnique: (id) => ({ id: Number.parseInt(id, 10) }),
fields: (t) => ({
title: t.exposeString('title'),
author: t.relation('author'),
}),
});When executing the node(id: ID!) query with a global ID for which prisma cannot find a record in
the database, the default behavior is to throw an error. There are some scenarios where it is
preferable to return null instead of throwing an error. For this you can add the nullable: true
option:
builder.prismaNode('Post', {
id: { field: 'id' },
nullable: true,
fields: (t) => ({
title: t.exposeString('title'),
author: t.relation('author'),
}),
});Refetch a public author
The publishing schema defines User as a Relay node. Its returned ID can be passed back to
node to fetch the author with a new selection:
query RefetchAuthor {
node(id: "VXNlcjox") {
... on User {
name
posts {
title
}
}
}
}The ID identifies User 1. The node returns the same public fields as the author lookup, including only published posts. A node lookup does not route through a custom root resolver, so any access restrictions on an entity must also hold when it is loaded as a node.
Post node lookups additionally restrict rows to published posts or the requesting author's own
drafts. With nullable: true, a missing or inaccessible Post returns null. Merely hiding a draft
from the public connection would not prevent a client from refetching it by a known node ID.