Skip to content

Commit

Permalink
feat: add option to specify paginationResolverName
Browse files Browse the repository at this point in the history
Closes #6
  • Loading branch information
nodkz committed Mar 15, 2019
1 parent fc429ac commit 5fa9964
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ import composeWithPagination from 'graphql-compose-pagination';
import userTypeComposer from './user.js';

composeWithPagination(userTypeComposer, {
paginationResolverName: 'pagination', // Default
findResolverName: 'findMany',
countResolverName: 'count',
perPage: 20, // Default
});
```

Expand Down
44 changes: 44 additions & 0 deletions src/__tests__/composeWithPagination-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,50 @@ describe('composeWithRelay', () => {
expect(myTC.getResolver('pagination')).toBeTruthy();
expect(myTC.getResolver('pagination').resolve()).toBe('mockData');
});

it('should add resolver with user-specified name', () => {
let myTC = TypeComposer.create('type CustomComplex { a: String, b: Int }');
myTC.addResolver({
name: 'count',
resolve: () => 1,
});
myTC.addResolver({
name: 'findMany',
resolve: () => ['mockData'],
});
myTC = composeWithPagination(myTC, {
paginationResolverName: 'customPagination',
countResolverName: 'count',
findResolverName: 'findMany',
});

expect(myTC.getResolver('customPagination')).toBeTruthy();
expect(myTC.hasResolver('pagination')).toBeFalsy();
});

it('should add two connection resolvers', () => {
let myTC = TypeComposer.create('type CustomComplex { a: String, b: Int }');
myTC.addResolver({
name: 'count',
resolve: () => 1,
});
myTC.addResolver({
name: 'findMany',
resolve: () => ['mockData'],
});
myTC = composeWithPagination(myTC, {
countResolverName: 'count',
findResolverName: 'findMany',
});
myTC = composeWithPagination(myTC, {
paginationResolverName: 'customPagination',
countResolverName: 'count',
findResolverName: 'findMany',
});

expect(myTC.hasResolver('pagination')).toBeTruthy();
expect(myTC.getResolver('customPagination')).toBeTruthy();
});
});

describe('check `pagination` resolver props', () => {
Expand Down
12 changes: 9 additions & 3 deletions src/composeWithPagination.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/* @flow */

import { TypeComposer } from 'graphql-compose';
import { preparePaginationResolver, type ComposeWithPaginationOpts } from './paginationResolver';
import {
preparePaginationResolver,
type ComposeWithPaginationOpts,
DEFAULT_RESOLVER_NAME,
} from './paginationResolver';

export function composeWithPagination(
typeComposer: TypeComposer,
Expand All @@ -15,12 +19,14 @@ export function composeWithPagination(
throw new Error('You should provide non-empty options to composeWithPagination');
}

if (typeComposer.hasResolver('pagination')) {
const resolverName = opts.paginationResolverName || DEFAULT_RESOLVER_NAME;

if (typeComposer.hasResolver(resolverName)) {
return typeComposer;
}

const resolver = preparePaginationResolver(typeComposer, opts);

typeComposer.setResolver('pagination', resolver);
typeComposer.setResolver(resolverName, resolver);
return typeComposer;
}
10 changes: 7 additions & 3 deletions src/paginationResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import type {
import type { GraphQLResolveInfo } from 'graphql-compose/lib/graphql';
import { preparePaginationTC } from './types/preparePaginationType';

const DEFAULT_PER_PAGE = 20;
export const DEFAULT_RESOLVER_NAME = 'pagination';
export const DEFAULT_PER_PAGE = 20;

export type ComposeWithPaginationOpts = {
paginationResolverName?: string,
findResolverName: string,
countResolverName: string,
perPage?: number,
Expand Down Expand Up @@ -56,6 +58,8 @@ export function preparePaginationResolver(
throw new Error('First arg for prepareConnectionResolver() should be instance of TypeComposer');
}

const resolverName = opts.paginationResolverName || DEFAULT_RESOLVER_NAME;

if (!opts.countResolverName) {
throw new Error(
`TypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
Expand Down Expand Up @@ -103,8 +107,8 @@ export function preparePaginationResolver(
}

return new tc.constructor.schemaComposer.Resolver({
type: preparePaginationTC(tc),
name: 'pagination',
type: preparePaginationTC(tc, resolverName),
name: resolverName,
kind: 'query',
args: {
page: {
Expand Down
18 changes: 18 additions & 0 deletions src/types/__tests__/preparePaginationType-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,28 @@ describe('preparePaginationTC()', () => {
expect(preparePaginationTC(UserTC)).toBeInstanceOf(TypeComposer);
});

it('should return the same Type object when called again', () => {
const firstPaginationType = preparePaginationTC(UserTC);
const secondPaginationType = preparePaginationTC(UserTC);
expect(firstPaginationType).toBe(secondPaginationType);
});

it('should return a separate GraphQLObjectType with a different name', () => {
const paginationType = preparePaginationTC(UserTC);
const otherPaginationType = preparePaginationTC(UserTC, 'otherPagination');
expect(paginationType).not.toBe(otherPaginationType);
});

it('should have name ending with `Pagination`', () => {
expect(preparePaginationTC(UserTC).getTypeName()).toBe('UserPagination');
});

it('should have name ending with `OtherPagination` when passed lowercase otherPagination', () => {
expect(preparePaginationTC(UserTC, 'otherConnection').getTypeName()).toBe(
'UserOtherConnection'
);
});

it('should have field `count` with provided Type', () => {
const tc = preparePaginationTC(UserTC);
expect(tc.getFieldType('count')).toBe(GraphQLInt);
Expand Down
7 changes: 4 additions & 3 deletions src/types/preparePaginationType.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* @flow */
/* eslint-disable arrow-body-style */

import type { TypeComposer, SchemaComposer } from 'graphql-compose';
import { upperFirst, type TypeComposer, type SchemaComposer } from 'graphql-compose';

export function preparePaginationInfoTC(schemaComposer: SchemaComposer<any>): TypeComposer {
return schemaComposer.getOrCreateTC('PaginationInfo', tc => {
Expand Down Expand Up @@ -35,9 +35,10 @@ export function preparePaginationInfoTC(schemaComposer: SchemaComposer<any>): Ty
});
}

export function preparePaginationTC(tc: TypeComposer): TypeComposer {
export function preparePaginationTC(tc: TypeComposer, resolverName: ?string): TypeComposer {
const schemaComposer = tc.constructor.schemaComposer;
const name = `${tc.getTypeName()}Pagination`;

const name = `${tc.getTypeName()}${upperFirst(resolverName || 'pagination')}`;
const type = tc.getType();

if (schemaComposer.has(name)) {
Expand Down

0 comments on commit 5fa9964

Please sign in to comment.