diff --git a/src/graphql/createTableType.js b/src/graphql/createTableType.js index 874bd79fa1..b83808a200 100644 --- a/src/graphql/createTableType.js +++ b/src/graphql/createTableType.js @@ -1,6 +1,6 @@ import { memoize, fromPairs, camelCase } from 'lodash' -import { GraphQLObjectType } from 'graphql' -import { IDType, NodeType } from './types.js' +import { GraphQLObjectType, GraphQLID } from 'graphql' +import { NodeType, toID } from './types.js' import getColumnType from './getColumnType.js' import resolveTableSingle from './resolveTableSingle.js' import createConnectionType from './createConnectionType.js' @@ -51,12 +51,9 @@ const createTableType = memoize(table => { // anything. ...(isNode ? { id: { - type: IDType, + type: GraphQLID, description: `The globally unique identifier for this ${table.getMarkdownTypeName()}.`, - resolve: source => ({ - tableName: table.name, - values: primaryKeyColumns.map(column => source[column.name]), - }), + resolve: source => toID(table.name, primaryKeyColumns.map(column => source[column.name])), }, } : {}), ...fromPairs( diff --git a/src/graphql/query/createNodeQueryField.js b/src/graphql/query/createNodeQueryField.js index 4e3924e46d..13e9556310 100644 --- a/src/graphql/query/createNodeQueryField.js +++ b/src/graphql/query/createNodeQueryField.js @@ -1,6 +1,6 @@ import { memoize } from 'lodash' -import { GraphQLNonNull } from 'graphql' -import { NodeType, IDType } from '../types.js' +import { GraphQLNonNull, GraphQLID } from 'graphql' +import { NodeType, fromID } from '../types.js' import resolveTableSingle from '../resolveTableSingle.js' const createNodeQueryField = schema => ({ @@ -9,19 +9,20 @@ const createNodeQueryField = schema => ({ args: { id: { - type: new GraphQLNonNull(IDType), + type: new GraphQLNonNull(GraphQLID), description: 'The `ID` of the node.', }, }, resolve: (source, args, context) => { const { id } = args - const table = schema.getTable(id.tableName) + const { tableName, values } = fromID(id) + const table = schema.getTable(tableName) if (!table) - throw new Error(`No table '${id.tableName}' in schema '${schema.name}'.`) + throw new Error(`No table '${tableName}' in schema '${schema.name}'.`) - return getResolver(table)(source, args, context) + return getResolver(table)({ values }, {}, context) }, }) @@ -32,5 +33,5 @@ export default createNodeQueryField const getResolver = memoize(table => resolveTableSingle( table, table.getPrimaryKeyColumns(), - (source, args) => args.id.values, + ({ values }) => values, )) diff --git a/src/graphql/query/createSingleQueryField.js b/src/graphql/query/createSingleQueryField.js index 632ce49279..dba6e63d40 100644 --- a/src/graphql/query/createSingleQueryField.js +++ b/src/graphql/query/createSingleQueryField.js @@ -1,5 +1,5 @@ -import { GraphQLNonNull } from 'graphql' -import { IDType } from '../types.js' +import { GraphQLNonNull, GraphQLID } from 'graphql' +import { fromID } from '../types.js' import createTableType from '../createTableType.js' import resolveTableSingle from '../resolveTableSingle.js' @@ -22,7 +22,7 @@ const createSingleQueryField = table => { args: { id: { - type: new GraphQLNonNull(IDType), + type: new GraphQLNonNull(GraphQLID), description: `The \`ID\` of the ${table.getMarkdownTypeName()} node.`, }, }, @@ -30,7 +30,8 @@ const createSingleQueryField = table => { resolve: resolveTableSingle( table, primaryKeyColumns, - (source, { id: { tableName, values } }) => { + (source, { id }) => { + const { tableName, values } = fromID(id) if (tableName !== table.name) return null return values } diff --git a/src/graphql/types.js b/src/graphql/types.js index 669a2ee83c..32335d0c47 100644 --- a/src/graphql/types.js +++ b/src/graphql/types.js @@ -3,6 +3,7 @@ import { GraphQLBoolean, GraphQLInt, GraphQLFloat, + GraphQLID, GraphQLNonNull, GraphQLScalarType, GraphQLObjectType, @@ -29,9 +30,9 @@ const createStringScalarType = ({ name, description }) => * Node Types * ========================================================================= */ -const toID = id => toBase64(`${id.tableName}:${id.values.join(',')}`) +export const toID = (tableName, values) => toBase64(`${tableName}:${values.join(',')}`) -const fromID = encodedString => { +export const fromID = encodedString => { const string = fromBase64(encodedString) if (!string) throw new Error(`Invalid ID '${encodedString}'.`) const [tableName, valueString] = string.split(':', 2) @@ -40,24 +41,13 @@ const fromID = encodedString => { return { tableName, values } } -export const IDType = - new GraphQLScalarType({ - name: 'ID', - description: - 'A globally unique identifier used to refetch an object or as a key for a ' + - 'cache. It is not intended to be human readable.', - serialize: toID, - parseValue: fromID, - parseLiteral: ast => (ast.kind === Kind.STRING ? fromID(ast.value) : null), - }) - export const NodeType = new GraphQLInterfaceType({ name: 'Node', description: 'A single node object in the graph with a globally unique identifier.', fields: { id: { - type: IDType, + type: GraphQLID, description: 'The `Node`’s globally unique identifier used to refetch the node.', }, }, diff --git a/tests/graphql/createTableType.test.js b/tests/graphql/createTableType.test.js index 24e536c2ab..d88d801eb8 100644 --- a/tests/graphql/createTableType.test.js +++ b/tests/graphql/createTableType.test.js @@ -1,5 +1,5 @@ import expect from 'expect' -import { GraphQLObjectType } from 'graphql' +import { GraphQLObjectType, GraphQLID } from 'graphql' import { TestTable, TestColumn } from '../helpers.js' import createTableType from '#/graphql/createTableType.js' @@ -48,6 +48,7 @@ describe('createTableType', () => { const type = createTableType(new TestTable()) expect(type.getInterfaces()[0].name).toEqual('Node') expect(type.getFields()).toIncludeKey('id') + expect(type.getFields().id.type).toBe(GraphQLID) }) it('will not implement the `Node` type for tables without primary keys', () => { diff --git a/tests/graphql/query/createSingleQueryField.test.js b/tests/graphql/query/createSingleQueryField.test.js index 61d47295f4..27e058a0bb 100644 --- a/tests/graphql/query/createSingleQueryField.test.js +++ b/tests/graphql/query/createSingleQueryField.test.js @@ -1,6 +1,6 @@ import expect from 'expect' import { keys } from 'lodash' -import { GraphQLObjectType, GraphQLNonNull } from 'graphql' +import { GraphQLObjectType, GraphQLNonNull, GraphQLID } from 'graphql' import { TestTable, TestColumn } from '../../helpers.js' import createSingleQueryField from '#/graphql/query/createSingleQueryField.js' @@ -38,10 +38,10 @@ describe('createSingleQueryField', () => { expect(keys(person.args)).toEqual(['id']) expect(person.args.id.type).toBeA(GraphQLNonNull) - expect(person.args.id.type.ofType.name).toEqual('ID') + expect(person.args.id.type.ofType).toBe(GraphQLID) expect(keys(compoundKey.args)).toEqual(['id']) expect(compoundKey.args.id.type).toBeA(GraphQLNonNull) - expect(compoundKey.args.id.type.ofType.name).toEqual('ID') + expect(compoundKey.args.id.type.ofType).toBe(GraphQLID) }) it('it will return null for tables without primary keys', () => {