https://github.com/echobind/nexus-pagination-plugin
A plugin for adding offset-based pagination to your nexus types
https://github.com/echobind/nexus-pagination-plugin
Last synced: 4 months ago
JSON representation
A plugin for adding offset-based pagination to your nexus types
- Host: GitHub
- URL: https://github.com/echobind/nexus-pagination-plugin
- Owner: echobind
- Created: 2021-12-01T22:23:36.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2022-03-15T19:08:15.000Z (about 4 years ago)
- Last Synced: 2025-02-16T12:13:56.175Z (over 1 year ago)
- Language: TypeScript
- Size: 51.8 KB
- Stars: 0
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# nexus-pagination-plugin
nexus-pagination-plugin
This pagination plugin provides a new method on the object definition builder, enabling paginated associations between types, following the offset-based pagination standard defined below.
## Offset-Based Pagination Standard
A paginated query field should receive two arguments:
* `page`
* The current page being request. Defaults to 1
* `pageSize`
* The size of pages being used. Defaults to 25
A paginated query field should return a type that contains the following:
* `results`
* A collection of the data requested
* `pageInfo`
* A type that contains information about the pagination
* `page`
* `nextPage`
* `totalPages`
## Installation
```
yarn add nexus-pagination-plugin
```
or
```
npm install nexus-pagination-plugin
```
## Setup
```ts
import { makeSchema} from 'nexus';
import { paginationPlugin } from 'nexus-pagination-plugin';
export const schema = makeSchema({
// ... types, etc,
plugins: [
// ... other plugins
paginationPlugin()
],
});
```
## Example Usage
This plugin surfaces a `t.paginatedQueryResult` function that can be used to add pagination to a given type.
```ts
// User Type
export const User = objectType({
name: 'User',
description: 'A User',
definition(t) {
t.nonNull.id('id');
t.nonNull.string('firstName');
t.nonNull.string('lastName');
},
});
// add paginated users query
export const UsersQuery = queryField((t) => {
t.paginatedQueryResult('users', {
type: 'User',
resolve: async (_root, args, ctx) => {
const { take, skip } = ctx.paginationParams;
const users = await ctx.prisma.user.findMany({
skip,
take,
});
const usersCount = await ctx.prisma.user.count();
const pageInfo = ctx.calculatePageInfo(usersCount);
return {
results: users,
pageInfo
}
},
})
})
```
## `resolve: (root, args, ctx) => ...`
`t.paginatedQueryResult` wraps the resolve function passed in the query config and adds the following fields on the context object.
### `ctx.paginationParams: {take: number, skip: number}`
* `take` specifies the page size
* `skip` specifies how many to skip based on the page size and page arguments
### `ctx.calculatePageInfo: (count: number) => PageInfo`
* `count` specifies the total count of records in the DB
* Returns type [`PageInfo`](#pageinfo)
## Generated Types
### `PageInfo`
```ts
objectType({
name: 'PageInfo',
definition(t) {
t.int('page');
t.int('nextPage');
t.int('totalPages');
},
})
```
### `Paginated${targeTypename}s`
```ts
objectType({
name: generatedTypeName,
definition(t2) {
t2.nonNull.list.field('results', {
type: fieldConfig.type,
description: `Collection of ${fieldName}`,
});
t2.nonNull.field('pageInfo', {
type: 'PageInfo',
description: 'Pagination information',
});
},
})
```
For a paginated field defined on `Query` like this:
```ts
queryField((t) => {
t.paginatedQueryField('foos', {
type: 'Foo',
// ... any additional query config
});
});
```
The following types would be generated:
```gql
type PageInfo {
nextPage: Int
page: Int
totalPages: Int
}
type PaginatedFoos {
pageInfo: PageInfo!
results: [Foo]!
}
type Query {
""" ... other Query fields """
foos(
page: Int = 1,
pageSize: Int = 25
): PaginatedFoos
}
```
Note that the collection type will be added to whatever parent type is specified. This means that if you were to define a paginated field on another object rather than on `Query` like this:
```ts
objectType({
type: 'Bar',
definition(t) {
// ... other definitions
t.paginatedQueryField('foos', {
type: 'Foo',
// ... any additional query config
});
}
})
```
The `foos` query would be added to the `Bar` type rather than the `Query` type:
```gql
type Bar {
""" ... other Bar fields """
foos(
page: Int = 1
pageSize: Int = 25
): PaginatedFoos
}
```
## Options
### `defaultPageSize: number`
Used to specify a different default for the generated `pageSize` argument. Defaults to 25
Global usage:
```ts
paginationPlugin({
defaultPageSize: 10
})
```
Field usage:
```ts
export const UsersQuery = queryField((t) => {
t.paginatedQueryResult('users', {
// ... any additional query fields
defaultPageSize: 10
})
})
```
### `getGeneratedTypename: (targetTypename: string) => string`
Used to specify a different generated typename for the paginated types. Defaults to `Paginated${targetTypename}s`
Usage:
```ts
paginationPlugin({
getGeneratedTypename: (targetTypename) => `${targetTypename}sPaginated`
})
```
### `generatedTypename: string`
Used to specify a different generated typename for a specific field. Defaults to `Paginated${targetTypename}s` or whatever is defined by `getGeneratedTypename`
Usage:
```ts
export const FinishesQuery = queryField((t) => {
t.paginatedQueryResult('finishes', {
type: 'Finish',
// ... any additional query fields
generatedTypename: 'PaginatedFinishes'
})
})
```