diff --git a/src/buildSortFromArg.ts b/src/buildSortFromArg.ts deleted file mode 100644 index 4a0f853..0000000 --- a/src/buildSortFromArg.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { GraphqlSortArg } from './types'; - -export type SortObject = { - [key: string]: 1 | -1; -}; - -export default function buildSortFromArg( - orderByArg: GraphqlSortArg[], -): SortObject { - return orderByArg.reduce( - (acc, item) => ({ - ...acc, - [item.field]: item.direction, - }), - {}, - ); -} diff --git a/src/connectionDefinitions.ts b/src/connectionDefinitions.ts index 3d2cba6..02b4e98 100644 --- a/src/connectionDefinitions.ts +++ b/src/connectionDefinitions.ts @@ -1,156 +1,34 @@ import { - GraphQLBoolean, - GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLFieldResolver, GraphQLInt, - GraphQLInterfaceType, - GraphQLList, GraphQLNonNull, GraphQLObjectType, - GraphQLString, Thunk, } from 'graphql'; - -export const forwardConnectionArgs: GraphQLFieldConfigArgumentMap = { - after: { - type: GraphQLString, - }, - first: { - type: GraphQLInt, - }, -}; - -export const backwardConnectionArgs: GraphQLFieldConfigArgumentMap = { - before: { - type: GraphQLString, - }, - last: { - type: GraphQLInt, - }, -}; - -export const connectionArgs: GraphQLFieldConfigArgumentMap = { - ...forwardConnectionArgs, - ...backwardConnectionArgs, -}; - -export type GraphQLConnectionDefinitions = { - edgeType: GraphQLObjectType; - connectionType: GraphQLObjectType; -}; - -export const PageInfoType = new GraphQLObjectType({ - name: 'PageInfo', - description: 'Information about pagination in a connection.', - fields: () => ({ - hasNextPage: { - type: GraphQLNonNull(GraphQLBoolean), - description: 'When paginating forwards, are there more items?', - }, - hasPreviousPage: { - type: GraphQLNonNull(GraphQLBoolean), - description: 'When paginating backwards, are there more items?', - }, - startCursor: { - type: GraphQLString, - description: 'When paginating backwards, the cursor to continue.', - }, - endCursor: { - type: GraphQLString, - description: 'When paginating forwards, the cursor to continue.', - }, - }), -}); - -const connectionProps = { - count: { - type: GraphQLInt, - description: 'Number of items in this connection.', - }, - totalCount: { - type: GraphQLInt, - resolve: (connection) => connection.count, - description: `A count of the total number of objects in this connection, ignoring pagination. -This allows a client to fetch the first five objects by passing "5" as the -argument to "first", then fetch the total count so it could display "5 of 83", -for example.`, - }, - startCursorOffset: { - type: GraphQLNonNull(GraphQLInt), - description: 'Offset from start.', - }, - endCursorOffset: { - type: GraphQLNonNull(GraphQLInt), - description: 'Offset till end.', - }, - pageInfo: { - type: GraphQLNonNull(PageInfoType), - description: 'Information to aid in pagination.', - }, -}; - -export const ConnectionInterface = new GraphQLInterfaceType({ - name: `Connection`, - description: 'A connection to a list of items.', - fields: () => ({ - ...connectionProps, - }), -}); - -function resolveMaybeThunk(thingOrThunk: Thunk): T { - return typeof thingOrThunk === 'function' ? (thingOrThunk as () => T)() : thingOrThunk; -} +import { connectionDefinitions as connectionDefinitionsRelay } from 'graphql-relay'; interface ConnectionConfig { - name?: string | null; - description?: string | null; + name?: string; nodeType: GraphQLObjectType; - edgeDescription?: string | null; - resolveNode?: GraphQLFieldResolver | null; - resolveCursor?: GraphQLFieldResolver | null; - edgeFields?: Thunk> | null; - connectionFields?: Thunk> | null; + resolveNode?: GraphQLFieldResolver; + resolveCursor?: GraphQLFieldResolver; + edgeFields?: Thunk>; + connectionFields?: Thunk>; } -export const connectionDefinitions = (config: ConnectionConfig): GraphQLConnectionDefinitions => { - const { nodeType, resolveCursor, resolveNode } = config; - - const name = config.name || nodeType.name; - const edgeFields = config.edgeFields || {}; - const connectionFields = config.connectionFields || {}; - - const edgeType = new GraphQLObjectType({ - name: `${name}Edge`, - description: config.edgeDescription || 'An edge in a connection.', - fields: () => ({ - node: { - type: nodeType, - resolve: resolveNode, - description: 'The item at the end of the edge.', - }, - cursor: { - type: GraphQLNonNull(GraphQLString), - resolve: resolveCursor, - description: 'A cursor for use in pagination.', +export const connectionDefinitions = (config: ConnectionConfig) => { + return connectionDefinitionsRelay({ + ...config, + connectionFields: { + startCursorOffset: { + type: GraphQLNonNull(GraphQLInt), + description: 'Offset from start.', }, - ...(resolveMaybeThunk(edgeFields) as any), - }), - }); - - const connectionType = new GraphQLObjectType({ - name: `${name}Connection`, - description: config.description || 'A connection to a list of items.', - fields: () => ({ - ...connectionProps, - edges: { - type: GraphQLNonNull(GraphQLList(edgeType)), - description: 'A list of edges.', + endCursorOffset: { + type: GraphQLNonNull(GraphQLInt), + description: 'Offset till end.', }, - ...(resolveMaybeThunk(connectionFields) as any), - }), - interfaces: [ConnectionInterface], + }, }); - - return { edgeType, connectionType }; }; diff --git a/src/DirectionEnumType.ts b/src/sorting/DirectionEnumType.ts similarity index 100% rename from src/DirectionEnumType.ts rename to src/sorting/DirectionEnumType.ts diff --git a/src/__tests__/buildSortFromArg.spec.ts b/src/sorting/__tests__/buildSortFromArg.spec.ts similarity index 67% rename from src/__tests__/buildSortFromArg.spec.ts rename to src/sorting/__tests__/buildSortFromArg.spec.ts index 0d2fc7e..62c6de6 100644 --- a/src/__tests__/buildSortFromArg.spec.ts +++ b/src/sorting/__tests__/buildSortFromArg.spec.ts @@ -8,9 +8,7 @@ it('should return correct sort', async () => { }, ]; - expect(buildSortFromArg(sortArg)).toMatchInlineSnapshot(` -Object { - "user": -1, -} -`); + expect(buildSortFromArg(sortArg)).toEqual({ + user: -1, + }); }); diff --git a/src/sorting/buildSortFromArg.ts b/src/sorting/buildSortFromArg.ts new file mode 100644 index 0000000..33bc2b5 --- /dev/null +++ b/src/sorting/buildSortFromArg.ts @@ -0,0 +1,18 @@ +export type SortValues = 1 | -1 | number; + +export interface GraphqlSortArg { + field: SortFieldT; + direction: SortValues; +} + +export default function buildSortFromArg( + orderByArg: GraphqlSortArg[], +): Record { + return orderByArg.reduce( + (acc, item) => ({ + ...acc, + [item.field]: item.direction, + }), + {}, + ); +} diff --git a/src/sorting/createSortFieldType.ts b/src/sorting/createSortFieldType.ts new file mode 100644 index 0000000..cddab8a --- /dev/null +++ b/src/sorting/createSortFieldType.ts @@ -0,0 +1,24 @@ +import { GraphQLInputObjectType, GraphQLNonNull, GraphQLEnumType, GraphQLEnumValueConfigMap } from 'graphql'; + +import { DirectionEnumType } from './DirectionEnumType'; + +export const createSortFieldType = (name: string, values: GraphQLEnumValueConfigMap) => { + const SortFieldEnumType = new GraphQLEnumType({ + name: `${name}SortFieldEnum`, + values: values, + }); + + const SortInputType = new GraphQLInputObjectType({ + name: `${name}Sort`, + fields: () => ({ + field: { + type: GraphQLNonNull(SortFieldEnumType), + }, + direction: { + type: GraphQLNonNull(DirectionEnumType), + }, + }), + }); + + return { SortFieldEnumType, SortInputType }; +}; diff --git a/src/types.ts b/src/types.ts index 88bef7a..db18da6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -47,12 +47,4 @@ export interface GraphQLArgFilter { filter: GraphQLFilter; } -// this should be 1 | -1, but it's going to be harder to use from client if that was the case. -export type SortDirection = number; - -export interface GraphqlSortArg { - field: SortFieldT; - direction: SortDirection; -} - export type LoaderFn = (ctx: Context, id: DataLoaderKey) => any;