UNPKG

@sonibble-creators/nest-microservice-pack

Version:
121 lines (109 loc) 2.9 kB
import { ConnectionCursor, fromGlobalId } from 'graphql-relay'; import { PaginationArgs } from './pagination.args'; /** * use to get the id of the cursor * by manipulate the cursor * * @param cursor * @returns */ const getId = (cursor: ConnectionCursor) => parseInt(fromGlobalId(cursor).id, 10); /** * get the nextid * so we can use the id to get the next cursor * by manipulate the cursor * * * @param cursor * @returns */ const nextId = (cursor: ConnectionCursor) => getId(cursor) + 1; /** * ## PaginationPageParam * * The param for the pagination page * combine the limit and offset * * @param limit - limit of the data will be showed * @param offset - offset of the data will be showed * */ export type PaginationPageParam = { limit?: number; offset?: number; }; /** * get the paging meta * get the pagination parameters and meta */ export function getPagingParameters(args: PaginationArgs): PaginationPageParam { // find the meta, by checking the sanity of the pagination const meta = checkPagingSanity(args); // start by switch the paging type // and get the paging parameters switch (meta.pagingType) { case 'forward': { return { limit: meta.first, offset: meta.after ? nextId(meta.after) : 0, }; } case 'backward': { const { last, before } = meta; let limit = last; let offset = getId(before!) - last; if (offset < 0) { limit = Math.max(last + offset, 0); offset = 0; } return { offset, limit }; } default: return { limit: 8, offset: 0, }; } } /** * ## PagingMeta * * Paging meta type * allow to manage the type of forward, backward, none * * */ type PagingMeta = | { pagingType: 'forward'; after?: string; first: number } | { pagingType: 'backward'; before?: string; last: number } | { pagingType: 'none' }; /** * ### checkPagingSanity * * Check the pagination sanity * @param args * @returns */ function checkPagingSanity(args: PaginationArgs): PagingMeta { const { first = 0, last = 0, after, before } = args; const isForwardPaging = !!first || !!after; const isBackwardPaging = !!last || !!before; if (isForwardPaging && isBackwardPaging) { throw new Error('Relay pagination cannot be forwards AND backwards!'); } if ((isForwardPaging && before) || (isBackwardPaging && after)) { throw new Error('Paging must use either first/after or last/before!'); } if ((isForwardPaging && first < 0) || (isBackwardPaging && last < 0)) { throw new Error('Paging limit must be positive!'); } if (last && !before) { throw new Error("When paging backwards, a 'before' argument is required!"); } return isForwardPaging ? { pagingType: 'forward', after, first } : isBackwardPaging ? { pagingType: 'backward', before, last } : { pagingType: 'none' }; }