Skip to content

Commit 47cd619

Browse files
committed
feat: better type definitions for Relay Modern
This update provides some changes for graphql connection type definitions. Now relay-compiler can generate better flowtype declarations, which will require less runtime checks in your code. Eg. - `edges` can not be empty and do not require additional check in your code is it null or not. - `cursor` now have regular `String` type, before it casted by relay-compiler to `any` flow type and does not provide proper checks out of the box.
1 parent c2ee041 commit 47cd619

6 files changed

+18
-33
lines changed

src/__tests__/composeWithConnection-test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/* eslint-disable no-param-reassign */
33

44
import { TypeComposer } from 'graphql-compose';
5-
import { GraphQLSchema, GraphQLList, graphql } from 'graphql-compose/lib/graphql';
5+
import { GraphQLSchema, GraphQLList, GraphQLNonNull, graphql } from 'graphql-compose/lib/graphql';
66
import { composeWithConnection } from '../composeWithConnection';
77
import { userTypeComposer, sortOptions } from '../__mocks__/userTypeComposer';
88
import { rootQueryTypeComposer as rootQueryTC } from '../__mocks__/rootQueryTypeComposer';
@@ -63,7 +63,8 @@ describe('composeWithRelay', () => {
6363
it('should has ConnectionType as type', () => {
6464
expect(type).toBeTruthy();
6565
expect(tc.getFieldNames()).toEqual(expect.arrayContaining(['count', 'pageInfo', 'edges']));
66-
expect(tc.getFieldType('edges')).toBeInstanceOf(GraphQLList);
66+
expect(tc.getFieldType('edges')).toBeInstanceOf(GraphQLNonNull);
67+
expect(tc.getFieldType('edges').ofType).toBeInstanceOf(GraphQLList);
6768
});
6869
});
6970

src/__tests__/connectionResolver-test.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22
/* eslint-disable no-param-reassign */
33

44
import { Resolver } from 'graphql-compose';
5-
import { GraphQLInt } from 'graphql-compose/lib/graphql';
5+
import { GraphQLInt, GraphQLString } from 'graphql-compose/lib/graphql';
66
import { userTypeComposer, userList, sortOptions } from '../__mocks__/userTypeComposer';
77
import { dataToCursor } from '../cursor';
88
import { prepareConnectionResolver, prepareRawQuery, preparePageInfo } from '../connectionResolver';
9-
import Cursor from '../types/cursorType';
109

1110
describe('connectionResolver', () => {
1211
const connectionResolver = prepareConnectionResolver(userTypeComposer, {
@@ -92,12 +91,12 @@ describe('connectionResolver', () => {
9291

9392
it('should have `after` arg', () => {
9493
// $FlowFixMe
95-
expect(connectionResolver.getArg('after').type).toBe(Cursor);
94+
expect(connectionResolver.getArg('after').type).toBe(GraphQLString);
9695
});
9796

9897
it('should have `before` arg', () => {
9998
// $FlowFixMe
100-
expect(connectionResolver.getArg('before').type).toBe(Cursor);
99+
expect(connectionResolver.getArg('before').type).toBe(GraphQLString);
101100
});
102101

103102
it('should have `sort` arg', () => {

src/connectionResolver.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import type { ResolveParams, ProjectionType } from 'graphql-compose';
66
import type { GraphQLResolveInfo } from 'graphql-compose/lib/graphql';
77
import { prepareConnectionType } from './types/connectionType';
88
import { prepareSortType } from './types/sortInputType';
9-
import CursorType from './types/cursorType';
109
import { cursorToData, dataToCursor, type CursorDataType } from './cursor';
1110
import type { ComposeWithConnectionOpts } from './composeWithConnection';
1211

@@ -124,15 +123,15 @@ export function prepareConnectionResolver<TSource, TContext>(
124123
description: 'Forward pagination argument for returning at most first edges',
125124
},
126125
after: {
127-
type: CursorType,
126+
type: 'String',
128127
description: 'Forward pagination argument for returning at most first edges',
129128
},
130129
last: {
131130
type: 'Int',
132131
description: 'Backward pagination argument for returning at most last edges',
133132
},
134133
before: {
135-
type: CursorType,
134+
type: 'String',
136135
description: 'Backward pagination argument for returning at most last edges',
137136
},
138137
...additionalArgs,

src/types/__tests__/connectionType-test.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import {
66
GraphQLObjectType,
77
getNamedType,
88
GraphQLInt,
9+
GraphQLString,
910
GraphQLList,
1011
} from 'graphql-compose/lib/graphql';
1112
import { userTypeComposer } from '../../__mocks__/userTypeComposer';
1213
import { prepareEdgeType, prepareConnectionType } from '../connectionType';
13-
import GraphQLConnectionCursor from '../cursorType';
1414
import PageInfoType from '../pageInfoType';
1515

1616
describe('types/connectionType.js', () => {
@@ -28,12 +28,12 @@ describe('types/connectionType.js', () => {
2828
expect(tc.getFieldType('node')).toBe(userTypeComposer.getType());
2929
});
3030

31-
it('should have field `cursor` with GraphQLNonNull(GraphQLConnectionCursor)', () => {
31+
it('should have field `cursor` with GraphQLNonNull(GraphQLString)', () => {
3232
const tc = new TypeComposer(prepareEdgeType(userTypeComposer));
3333
expect(tc.getFieldType('cursor')).toBeInstanceOf(GraphQLNonNull);
3434

3535
const cursor = getNamedType(tc.getFieldType('cursor'));
36-
expect(cursor).toBe(GraphQLConnectionCursor);
36+
expect(cursor).toBe(GraphQLString);
3737
});
3838

3939
it('should have `ofType` property (like GraphQLList, GraphQLNonNull)', () => {
@@ -73,7 +73,8 @@ describe('types/connectionType.js', () => {
7373

7474
it('should have field `edges` with GraphQLList(EdgeType)', () => {
7575
const tc = new TypeComposer(prepareConnectionType(userTypeComposer));
76-
expect(tc.getFieldType('edges')).toBeInstanceOf(GraphQLList);
76+
expect(tc.getFieldType('edges')).toBeInstanceOf(GraphQLNonNull);
77+
expect(tc.getFieldType('edges').ofType).toBeInstanceOf(GraphQLList);
7778

7879
const edges = getNamedType(tc.getFieldType('edges'));
7980
// $FlowFixMe

src/types/connectionType.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
import {
55
GraphQLInt,
6+
GraphQLString,
67
GraphQLObjectType,
78
GraphQLNonNull,
89
GraphQLList,
910
} from 'graphql-compose/lib/graphql';
1011
import type { TypeComposer } from 'graphql-compose';
11-
import GraphQLConnectionCursor from './cursorType';
1212

1313
import PageInfoType from './pageInfoType';
1414

@@ -32,7 +32,7 @@ export function prepareEdgeType(typeComposer: TypeComposer): GraphQLObjectType {
3232
description: 'The item at the end of the edge',
3333
},
3434
cursor: {
35-
type: new GraphQLNonNull(GraphQLConnectionCursor),
35+
type: new GraphQLNonNull(GraphQLString),
3636
description: 'A cursor for use in pagination',
3737
},
3838
}),
@@ -68,7 +68,9 @@ export function prepareConnectionType(typeComposer: TypeComposer): GraphQLObject
6868
description: 'Information to aid in pagination.',
6969
},
7070
edges: {
71-
type: new GraphQLList(prepareEdgeType(typeComposer)),
71+
type: new GraphQLNonNull(
72+
new GraphQLList(new GraphQLNonNull(prepareEdgeType(typeComposer)))
73+
),
7274
description: 'Information to aid in pagination.',
7375
},
7476
}),

src/types/cursorType.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)