graphql-compose-pagination
Version:
Plugin for `graphql-compose` which provide a pagination resolver for types.
123 lines • 5.86 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.preparePaginationResolver = exports.DEFAULT_PER_PAGE = exports.DEFAULT_RESOLVER_NAME = void 0;
const graphql_compose_1 = require("graphql-compose");
const types_1 = require("./types");
exports.DEFAULT_RESOLVER_NAME = 'pagination';
exports.DEFAULT_PER_PAGE = 20;
const ALLOWED_TYPE_COMPOSERS = [
'ObjectTypeComposer',
'InterfaceTypeComposer',
'UnionTypeComposer',
'ScalarTypeComposer',
'EnumTypeComposer',
];
function preparePaginationResolver(tc, opts) {
if (!tc || !ALLOWED_TYPE_COMPOSERS.includes(tc.constructor.name)) {
throw new Error(`First arg for preparePaginationResolver() should be instance of ${ALLOWED_TYPE_COMPOSERS.join(' or ')}`);
}
const resolverName = opts.name || exports.DEFAULT_RESOLVER_NAME;
if (!opts.countResolver || !(opts.countResolver instanceof graphql_compose_1.Resolver)) {
throw new Error(`Option 'opts.countResolver' must be a Resolver instance. Received ${graphql_compose_1.inspect(opts.countResolver)}`);
}
const countResolve = opts.countResolver.getResolve();
if (!opts.findManyResolver || !(opts.findManyResolver instanceof graphql_compose_1.Resolver)) {
throw new Error(`Option 'opts.findManyResolver' must be a Resolver instance. Received ${graphql_compose_1.inspect(opts.findManyResolver)}`);
}
const findManyResolver = opts.findManyResolver;
const findManyResolve = findManyResolver.getResolve();
const additionalArgs = {};
if (findManyResolver.hasArg('filter')) {
const filter = findManyResolver.getArg('filter');
if (filter) {
additionalArgs.filter = filter;
}
}
if (findManyResolver.hasArg('sort')) {
const sort = findManyResolver.getArg('sort');
if (sort) {
additionalArgs.sort = sort;
}
}
return tc.schemaComposer.createResolver({
type: types_1.preparePaginationTC(tc, resolverName),
name: resolverName,
kind: 'query',
args: Object.assign({ page: {
type: 'Int',
description: 'Page number for displaying',
}, perPage: {
type: 'Int',
description: '',
defaultValue: opts.perPage || exports.DEFAULT_PER_PAGE,
} }, additionalArgs),
resolve: (rp) => __awaiter(this, void 0, void 0, function* () {
let countPromise;
let findManyPromise;
const { projection = {}, args, rawQuery } = rp;
const page = parseInt(args.page, 10) || 1;
if (page <= 0) {
throw new Error('Argument `page` should be positive number.');
}
const perPage = parseInt(args.perPage, 10) || opts.perPage || exports.DEFAULT_PER_PAGE;
if (perPage <= 0) {
throw new Error('Argument `perPage` should be positive number.');
}
const countParams = Object.assign(Object.assign({}, rp), { rawQuery, args: Object.assign(Object.assign({}, rp.args), { filter: Object.assign({}, rp.args.filter) }) });
if (projection.count ||
(projection.pageInfo && (projection.pageInfo.itemCount || projection.pageInfo.pageCount))) {
countPromise = countResolve(countParams);
}
else {
countPromise = Promise.resolve(0);
}
const findManyParams = Object.assign({}, rp);
if (projection && projection.items) {
findManyParams.projection = Object.assign(Object.assign({}, projection), projection.items);
}
else {
findManyParams.projection = Object.assign({}, projection);
}
const limit = perPage;
const skip = (page - 1) * perPage;
findManyParams.args.limit = limit + 1;
if (skip > 0) {
findManyParams.args.skip = skip;
}
rp.findManyResolveParams = findManyParams;
rp.countResolveParams = countParams;
if ((projection.count || projection.pageInfo) && Object.keys(projection).length === 1) {
findManyPromise = Promise.resolve([]);
}
else {
findManyPromise = findManyResolve(findManyParams);
}
return Promise.all([findManyPromise, countPromise]).then(([items, count]) => {
const result = {
count,
items: items.length > limit ? items.slice(0, limit) : items,
pageInfo: {
currentPage: page,
perPage,
itemCount: count,
pageCount: Math.ceil(count / perPage),
hasPreviousPage: page > 1,
hasNextPage: items.length > limit || page * perPage < count,
},
};
return result;
});
}),
});
}
exports.preparePaginationResolver = preparePaginationResolver;
//# sourceMappingURL=pagination.js.map