OpenAPI - Pagination
Psychic provides a nice wrapper around Dream's paginate
method within the OpenAPI decorator, to enable you to explicitly render the results of a paginate
call within Dream. When passing paginate: true
, to your OpenAPI decorator, Psychic will automatically provide the necessary outer structure to reflect the call to Dream, and will correctly serialize the results
field on the incoming payload, same as it would in an ordinary many: true
scenario.
class PlacesController {
@OpenAPI(Place, {
paginate: true,
serializerKey: 'summary',
})
public async index() {
const paginated = await this.currentHost.associationQuery('places').paginate({
page: this.castParam('page', 'integer', { allowNull: true }),
pageSize: this.castParam('pageSize', 'integer', { allowNull: true }),
})
this.ok(paginated)
}
}
which will produce an openapi shape like this for the response body:
{
"type": "object",
"required": ["recordCount", "pageCount", "currentPage", "results"],
"properties": {
"recordCount": {
"type": "number"
},
"pageCount": {
"type": "number"
},
"currentPage": {
"type": "number"
},
"results": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PostSummary"
}
}
}
}
Scroll Pagination (Cursor-Based)
For high-performance scenarios with large datasets, use scrollPaginate: true
instead of paginate: true
to enable cursor-based pagination:
class PlacesController {
@OpenAPI(Place, {
scrollPaginate: true,
serializerKey: 'summary',
})
public async index() {
const paginated = await this.currentHost.associationQuery('places').scrollPaginate({
pageSize: this.castParam('pageSize', 'integer', { allowNull: true }),
cursor: this.castParam('cursor', 'string', { allowNull: true }),
})
this.ok(paginated)
}
}
This produces a different OpenAPI shape optimized for cursor-based navigation:
{
"type": "object",
"required": ["cursor", "results"],
"properties": {
"cursor": {
"type": "string",
"nullable": true,
"description": "Cursor for next page, null if no more pages"
},
"results": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PlaceSummary"
}
}
}
}
Scroll pagination provides better performance than offset-based pagination by avoiding expensive OFFSET queries. It's ideal for infinite scroll UX patterns and remains consistent when new records are added during navigation. Use cursor: null
for the first page, then pass the returned cursor
value for subsequent pages.