@sonibble-creators/nest-microservice-pack
Version:
Microservice pack dependencies for NestJS
121 lines (109 loc) • 2.9 kB
text/typescript
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' };
}