README
A fork of prisma-relay-cursor-connection with PR #366
prisma-relay-cursor-connection
Extend Prisma's findMany
method to support Relay Cursor Connections
Installation • Usage • Contributing • Contributors • License
Installation
yarn add @devoxa/prisma-relay-cursor-connection
This module has a peer dependency on @prisma/client
version ^2.0.0 || ^3.0.0
.
Usage
General Usage
This module validates the connection arguments to make sure they work with Prisma. The following combinations are supported:
{}
All resources{ first: number }
The first X resources{ first: number, after: string }
The first X resources after the id Y{ last: number }
The last X resources{ last: number, before: string }
The last X resources before the id Y
Two cases need to be checked in your code if you are passing in user-provided data to prevent the user from reading out too many resources at once:
- One of
first
|last
has to be defined first
|last
have to be below a reasonable maximum (e.g. 100)
import {
findManyCursorConnection,
ConnectionArguments,
} from '@devoxa/prisma-relay-cursor-connection'
const result = await findManyCursorConnection(
(args) => client.todo.findMany(args),
() => client.todo.count(),
{ first: 5, after: '5c11e0fa-fd6b-44ee-9016-0809ee2f2b9a' } // typeof ConnectionArguments
)
Type-Safe Arguments
You can also use additional FindManyArgs
while keeping type safety intact:
import { findManyCursorConnection } from '@devoxa/prisma-relay-cursor-connection'
const baseArgs = {
select: { id: true, isCompleted: true },
where: { isCompleted: true },
}
const result = await findManyCursorConnection(
(args) => client.todo.findMany({ ...args, ...baseArgs }),
() => client.todo.count({ where: baseArgs.where }),
{ last: 5, before: '5c11e0fa-fd6b-44ee-9016-0809ee2f2b9a' }
)
// Type error: Property text does not exist
result.edges[0].node.text
Custom Cursors
By default, the cursor is the id
field of your model. If you would like to use a different field,
a compound index, or handle encoding/decoding, you can pass the following options:
import { findManyCursorConnection } from '@devoxa/prisma-relay-cursor-connection'
const result = await findManyCursorConnection(
(args) => client.todo.findMany(args),
() => client.todo.count(),
{ first: 5, after: 'eyJpZCI6MTZ9' },
{
getCursor: (record) => ({ id: record.id }),
encodeCursor: (cursor) => Buffer.from(JSON.stringify(cursor)).toString('base64'),
decodeCursor: (cursor) => JSON.parse(Buffer.from(cursor, 'base64').toString('ascii')),
}
)
You can find more examples for custom cursors in the unit tests.
Custom Edges & Nodes
By default, the edge consists of the cursor
and the node
. If you would like to add additional
fields to the edge or the node, you can pass the following option:
import { findManyCursorConnection } from '@devoxa/prisma-relay-cursor-connection'
const result = await findManyCursorConnection<
Todo,
{ id: string },
Todo & { extraNodeField: string },
{ extraEdgeField: string; cursor: string; node: Todo & { extraNodeField: string } }
>(
(args) => client.todo.findMany(args),
() => client.todo.count(),
{ first: 5, after: 'eyJpZCI6MTZ9' },
{
recordToEdge: (record) => ({
node: { ...record, extraNodeField: 'Foo' },
extraEdgeField: 'Bar',
}),
}
)
Pagination with Page Cursors
Cursor based pagination is effective when working with an infinite list, but when you want to
present a list of pagination buttons it can be hard to provide that user-interface without a lot of
additional work. The folks at Artsy came up with a schema extension and technique for pagination
with page links [via
pageCursors
](](https://artsy.github.io/blog/2020/01/21/graphql-relay-windowed-pagination/), this
is implemented in findManyCursorConnectionWithPageCursors
.
import { findManyCursorConnectionWithPageCursors } from '@devoxa/prisma-relay-cursor-connection'
const result = await findManyCursorConnectionWithPageCursors(
(args) => client.todo.findMany(args),
() => client.todo.count()
)
result.pageCursors
// { around: [{ cursor: "ArXdF...", isCurrent: true, page: 1 }, { cursor: "ArXdF...", isCurrent: false, page: 2 }]}
When working with page cursors, your prisma models must have an id String @id @default(cuid())
.
This shouldn't be too much of a constraint, as you will likely be using this for the
Object Identification pattern.
Contributing
# Setup the test database
yarn prisma migrate dev --preview-feature
# Run the tests
yarn test
Contributors
Thanks goes to these wonderful people (emoji key):
David Reeß 💻 📖 ⚠️ |
Sean Matheson 💻 ⚠️ |
Marc 💻 |
Jeong Seong Dae 💻 ⚠️ |
Ahmet Uysal 💻 ⚠️ |
Nick Randall 💻 |
Igor Urminček 📖 |
This project follows the all-contributors specification. Contributions of any kind welcome!
License
MIT