Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![Greenkeeper badge](https://badges.greenkeeper.io/graphql-compose/graphql-compose-pagination.svg)](https://greenkeeper.io/)

This is a plugin for [graphql-compose](https://github.com/graphql-compose/graphql-compose) family, which adds to the TypeComposer `pagination` resolver.
This is a plugin for [graphql-compose](https://github.com/graphql-compose/graphql-compose) family, which adds to the ObjectTypeComposer `pagination` resolver.

Live demo: [https://graphql-compose.herokuapp.com/](https://graphql-compose.herokuapp.com/)

Expand Down
42 changes: 21 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,33 @@
},
"homepage": "https://github.com/graphql-compose/graphql-compose-pagination",
"peerDependencies": {
"graphql-compose": ">=5.0.1 || >=4.0.0 || >=3.0.2"
"graphql-compose": ">=6.0.0"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-transform-flow-strip-types": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/plugin-proposal-object-rest-spread": "^7.3.4",
"@babel/plugin-transform-flow-strip-types": "^7.3.4",
"@babel/plugin-transform-runtime": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"@babel/preset-flow": "^7.0.0",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "^9.0.0",
"babel-jest": "^23.4.2",
"babel-eslint": "^10.0.1",
"babel-jest": "^24.5.0",
"cz-conventional-changelog": "^2.1.0",
"eslint": "^5.5.0",
"eslint": "^5.15.2",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-config-prettier": "^3.0.1",
"eslint-plugin-flowtype": "^2.50.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-prettier": "^2.6.2",
"flow-bin": "^0.80.0",
"graphql": "14.0.0",
"graphql-compose": "^5.0.1",
"jest": "^23.5.0",
"prettier": "^1.14.2",
"rimraf": "^2.6.2",
"semantic-release": "^15.9.12"
"eslint-config-prettier": "^4.1.0",
"eslint-plugin-flowtype": "^3.4.2",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-prettier": "^3.0.1",
"flow-bin": "^0.95.1",
"graphql": "14.1.1",
"graphql-compose": "^6.0.1",
"jest": "^24.5.0",
"prettier": "^1.16.4",
"rimraf": "^2.6.3",
"semantic-release": "^15.13.3"
},
"config": {
"commitizen": {
Expand Down
10 changes: 5 additions & 5 deletions src/__mocks__/User.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* @flow */
/* eslint-disable no-param-reassign */

import { TypeComposer, Resolver, EnumTypeComposer } from 'graphql-compose';
import { schemaComposer } from 'graphql-compose';

export const UserTC = TypeComposer.create(`
export const UserTC = schemaComposer.createObjectTC(`
type User {
id: Int
name: String
Expand Down Expand Up @@ -93,13 +93,13 @@ function prepareFilterFromArgs(resolveParams = {}) {
return filter;
}

export const findManyResolver = new Resolver({
export const findManyResolver = schemaComposer.createResolver({
name: 'findMany',
kind: 'query',
type: UserTC,
args: {
filter: filterArgConfig,
sort: EnumTypeComposer.create({
sort: schemaComposer.createEnumTC({
name: 'SortUserInput',
values: {
ID_ASC: { value: { id: 1 } },
Expand Down Expand Up @@ -132,7 +132,7 @@ export const findManyResolver = new Resolver({
});
UserTC.setResolver('findMany', findManyResolver);

export const countResolver = new Resolver({
export const countResolver = schemaComposer.createResolver({
name: 'count',
kind: 'query',
type: 'Int',
Expand Down
20 changes: 10 additions & 10 deletions src/__tests__/composeWithPagination-test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* @flow */
/* eslint-disable no-param-reassign */

import { TypeComposer, schemaComposer } from 'graphql-compose';
import { ObjectTypeComposer, schemaComposer } from 'graphql-compose';
import { GraphQLList, graphql } from 'graphql-compose/lib/graphql';
import { composeWithPagination } from '../composeWithPagination';
import { UserTC } from '../__mocks__/User';
Expand All @@ -14,15 +14,15 @@ describe('composeWithRelay', () => {
});

describe('basic checks', () => {
it('should return TypeComposer', () => {
expect(userComposer).toBeInstanceOf(TypeComposer);
it('should return ObjectTypeComposer', () => {
expect(userComposer).toBeInstanceOf(ObjectTypeComposer);
});

it('should throw error if first arg is not TypeComposer', () => {
it('should throw error if first arg is not ObjectTypeComposer', () => {
expect(() => {
const args: any = [123];
composeWithPagination(...args);
}).toThrowError('should provide TypeComposer instance');
}).toThrowError('should provide ObjectTypeComposer instance');
});

it('should throw error if options are empty', () => {
Expand All @@ -33,7 +33,7 @@ describe('composeWithRelay', () => {
});

it('should not change `pagination` resolver if exists', () => {
let myTC = TypeComposer.create('type Complex { a: String, b: Int }');
let myTC = schemaComposer.createObjectTC('type Complex { a: String, b: Int }');
myTC.addResolver({
name: 'pagination',
resolve: () => 'mockData',
Expand All @@ -46,11 +46,11 @@ describe('composeWithRelay', () => {
});

expect(myTC.getResolver('pagination')).toBeTruthy();
expect(myTC.getResolver('pagination').resolve()).toBe('mockData');
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 }');
let myTC = schemaComposer.createObjectTC('type CustomComplex { a: String, b: Int }');
myTC.addResolver({
name: 'count',
resolve: () => 1,
Expand All @@ -70,7 +70,7 @@ describe('composeWithRelay', () => {
});

it('should add two connection resolvers', () => {
let myTC = TypeComposer.create('type CustomComplex { a: String, b: Int }');
let myTC = schemaComposer.createObjectTC('type CustomComplex { a: String, b: Int }');
myTC.addResolver({
name: 'count',
resolve: () => 1,
Expand All @@ -97,7 +97,7 @@ describe('composeWithRelay', () => {
describe('check `pagination` resolver props', () => {
const rsv = userComposer.getResolver('pagination');
const type: any = rsv.getType();
const tc = new TypeComposer(type);
const tc = schemaComposer.createObjectTC(type);

it('should exists', () => {
expect(rsv).toBeTruthy();
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/paginationResolver-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ describe('paginationResolver', () => {
expect(paginationResolver).toBeInstanceOf(Resolver);
});

it('should throw error if first arg is not TypeComposer', () => {
it('should throw error if first arg is not ObjectTypeComposer', () => {
expect(() => {
const args: any = [123];
preparePaginationResolver(...args);
}).toThrowError('should be instance of TypeComposer');
}).toThrowError('should be instance of ObjectTypeComposer');
});

it('should throw error if opts.countResolverName are empty', () => {
Expand Down
14 changes: 8 additions & 6 deletions src/composeWithPagination.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
/* @flow */

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

export function composeWithPagination(
typeComposer: TypeComposer,
export function composeWithPagination<TSource, TContext>(
typeComposer: ObjectTypeComposer<TSource, TContext>,
opts: ComposeWithPaginationOpts
): TypeComposer {
if (!typeComposer || typeComposer.constructor.name !== 'TypeComposer') {
throw new Error('You should provide TypeComposer instance to composeWithPagination method');
): ObjectTypeComposer<TSource, TContext> {
if (!typeComposer || typeComposer.constructor.name !== 'ObjectTypeComposer') {
throw new Error(
'You should provide ObjectTypeComposer instance to composeWithPagination method'
);
}

if (!opts) {
Expand Down
37 changes: 18 additions & 19 deletions src/paginationResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import type {
Resolver,
TypeComposer,
ObjectTypeComposer,
ResolveParams, // eslint-disable-line
ProjectionType,
} from 'graphql-compose';
Expand Down Expand Up @@ -50,26 +50,28 @@ export type PaginationInfoType = {|
hasNextPage: boolean,
|};

export function preparePaginationResolver(
tc: TypeComposer,
export function preparePaginationResolver<TSource, TContext>(
tc: ObjectTypeComposer<TSource, TContext>,
opts: ComposeWithPaginationOpts
): Resolver {
if (!tc || tc.constructor.name !== 'TypeComposer') {
throw new Error('First arg for prepareConnectionResolver() should be instance of TypeComposer');
): Resolver<TSource, TContext> {
if (!tc || tc.constructor.name !== 'ObjectTypeComposer') {
throw new Error(
'First arg for prepareConnectionResolver() should be instance of ObjectTypeComposer'
);
}

const resolverName = opts.paginationResolverName || DEFAULT_RESOLVER_NAME;

if (!opts.countResolverName) {
throw new Error(
`TypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
`ObjectTypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
'should have option `opts.countResolverName`.'
);
}
const countResolver = tc.getResolver(opts.countResolverName);
if (!countResolver) {
throw new Error(
`TypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
`ObjectTypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
`should have resolver with name '${opts.countResolverName}' ` +
'due opts.countResolverName.'
);
Expand All @@ -78,14 +80,14 @@ export function preparePaginationResolver(

if (!opts.findResolverName) {
throw new Error(
`TypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
`ObjectTypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
'should have option `opts.findResolverName`.'
);
}
const findManyResolver = tc.getResolver(opts.findResolverName);
if (!findManyResolver) {
throw new Error(
`TypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
`ObjectTypeComposer(${tc.getTypeName()}) provided to composeWithConnection ` +
`should have resolver with name '${opts.findResolverName}' ` +
'due opts.countResolverName.'
);
Expand All @@ -106,8 +108,8 @@ export function preparePaginationResolver(
}
}

return new tc.constructor.schemaComposer.Resolver({
type: preparePaginationTC(tc, resolverName),
return tc.schemaComposer.createResolver({
type: preparePaginationTC(tc),
name: resolverName,
kind: 'query',
args: {
Expand All @@ -122,14 +124,11 @@ export function preparePaginationResolver(
},
...(additionalArgs: any),
},
// prettier-ignore
resolve: async /* :: <TContext> */(
rp /* : $Shape<PaginationResolveParams<TContext>> */
) => {
resolve: async (rp: $Shape<PaginationResolveParams<TContext>>) => {
let countPromise;
let findManyPromise;
const { projection = {}, args, rawQuery } = rp;
const findManyParams /* : $Shape<ResolveParams<any, TContext>> */ = {
const findManyParams: $Shape<ResolveParams<TSource, TContext, any>> = {
...rp,
};

Expand All @@ -142,7 +141,7 @@ export function preparePaginationResolver(
throw new Error('Argument `perPage` should be positive number.');
}

const countParams /* : $Shape<ResolveParams<any, TContext>> */ = {
const countParams: $Shape<ResolveParams<TSource, TContext, any>> = {
...rp,
rawQuery,
args: {
Expand Down Expand Up @@ -203,6 +202,6 @@ export function preparePaginationResolver(
};
return result;
});
}
},
});
}
10 changes: 5 additions & 5 deletions src/types/__tests__/preparePaginationType-test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/* @flow */

import { TypeComposer } from 'graphql-compose';
import { ObjectTypeComposer } from 'graphql-compose';
import { GraphQLNonNull, getNamedType, GraphQLInt, GraphQLList } from 'graphql-compose/lib/graphql';
import { UserTC } from '../../__mocks__/User';
import { preparePaginationTC, preparePaginationInfoTC } from '../preparePaginationType';

describe('preparePaginationTC()', () => {
it('should return TypeComposer', () => {
expect(preparePaginationTC(UserTC)).toBeInstanceOf(TypeComposer);
it('should return ObjectTypeComposer', () => {
expect(preparePaginationTC(UserTC)).toBeInstanceOf(ObjectTypeComposer);
});

it('should return the same Type object when called again', () => {
Expand Down Expand Up @@ -38,7 +38,7 @@ describe('preparePaginationTC()', () => {
});

it('should have field `pageInfo` with GraphQLNonNull(PaginationInfoType)', () => {
const PaginationInfoTC = preparePaginationInfoTC(UserTC.constructor.schemaComposer);
const PaginationInfoTC = preparePaginationInfoTC(UserTC.schemaComposer);
const tc = preparePaginationTC(UserTC);
expect(tc.getFieldType('pageInfo')).toBeInstanceOf(GraphQLNonNull);

Expand All @@ -61,7 +61,7 @@ describe('preparePaginationTC()', () => {
expect(connectionType.ofType).toEqual(UserTC.getType());
});

it('should return same type for same Type in TypeComposer', () => {
it('should return same type for same Type in ObjectTypeComposer', () => {
const t1 = preparePaginationTC(UserTC);
const t2 = preparePaginationTC(UserTC);
expect(t1).toEqual(t2);
Expand Down
20 changes: 12 additions & 8 deletions src/types/preparePaginationType.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/* @flow */
/* eslint-disable arrow-body-style */

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

export function preparePaginationInfoTC(schemaComposer: SchemaComposer<any>): TypeComposer {
return schemaComposer.getOrCreateTC('PaginationInfo', tc => {
export function preparePaginationInfoTC<TContext>(
schemaComposer: SchemaComposer<TContext>
): ObjectTypeComposer<any, TContext> {
return schemaComposer.getOrCreateOTC('PaginationInfo', tc => {
tc.setDescription('Information about pagination.');
tc.addFields({
currentPage: {
Expand Down Expand Up @@ -35,17 +37,19 @@ export function preparePaginationInfoTC(schemaComposer: SchemaComposer<any>): Ty
});
}

export function preparePaginationTC(tc: TypeComposer, resolverName: ?string): TypeComposer {
const schemaComposer = tc.constructor.schemaComposer;

export function preparePaginationTC<TSource, TContext>(
tc: ObjectTypeComposer<TSource, TContext>,
resolverName: ?string
): ObjectTypeComposer<TSource, TContext> {
const schemaComposer = tc.schemaComposer;
const name = `${tc.getTypeName()}${upperFirst(resolverName || 'pagination')}`;
const type = tc.getType();

if (schemaComposer.has(name)) {
return schemaComposer.getTC(name);
return schemaComposer.getOTC(name);
}

const paginationTC = schemaComposer.TypeComposer.create({
const paginationTC = schemaComposer.createObjectTC({
name,
description: 'List of items with pagination.',
fields: {
Expand Down
Loading