Skip to content

Commit

Permalink
Correctly create input types for arrays with objects #908
Browse files Browse the repository at this point in the history
  • Loading branch information
0x80 authored and KyleAMathews committed May 3, 2017
1 parent 6f6c61f commit 7b45d92
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 21 deletions.
30 changes: 30 additions & 0 deletions packages/gatsby/lib/schema/__tests__/infer-graphql-input-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ describe(`GraphQL Input args`, () => {
title: `The world of dash and adventure`,
blue: 100,
},
anObjectArray: [
{ aString: `some string`, aNumber: 2, aBoolean: true },
{ aString: `some string`, aNumber: 2, anArray: [1, 2] },
],
},
{
name: `The Mad Wax`,
Expand Down Expand Up @@ -258,4 +262,30 @@ describe(`GraphQL Input args`, () => {
expect(result.data.allNode.anArray[0].totalCount).toEqual(2)
})
.catch(err => expect(err).not.toBeDefined()))

it(`can query object arrays`, () =>
graphql(
schema,
`
{
allNode {
edges {
node {
anObjectArray {
aString
aNumber
aBoolean
}
}
}
}
}
`
)
.then(result => {
expect(result.errors).not.toBeDefined()

expect(result).toMatchSnapshot()
})
.catch(err => expect(err).not.toBeDefined()))
})
14 changes: 14 additions & 0 deletions packages/gatsby/lib/schema/create-type-name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const _ = require(`lodash`)

const seenNames = {}

module.exports = function createTypeName(name) {
const cameledName = _.camelCase(name)
if (seenNames[cameledName]) {
seenNames[cameledName] += 1
return `${cameledName}_${seenNames[cameledName]}`
} else {
seenNames[cameledName] = 1
return cameledName
}
}
25 changes: 16 additions & 9 deletions packages/gatsby/lib/schema/infer-graphql-input-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const {
GraphQLNonNull,
} = require(`graphql`)
const _ = require(`lodash`)
const moment = require(`moment`)
const typeOf = require(`type-of`)
const createTypeName = require(`./create-type-name`)

const {
extractFieldExamples,
Expand Down Expand Up @@ -54,10 +54,11 @@ const inferGraphQLInputFields = (exports.inferGraphQLInputFields = (
) => {
switch (typeOf(value)) {
case `array`:
let headType = typeOf(value[0])
const headValue = value[0]
let headType = typeOf(headValue)
// Check if headType is a number.
if (headType === `number`) {
if (value[0] % 1 === 0) {
if (headValue % 1 === 0) {
headType = `int`
} else {
headType = `float`
Expand All @@ -79,11 +80,17 @@ const inferGraphQLInputFields = (exports.inferGraphQLInputFields = (
case `boolean`:
inType = GraphQLBoolean
break
case `object`:
inType = inferGraphQLInputFields(headValue, key, nodes).type
break
case `array`:
inType = inferGraphQLInputFields(headValue, key, nodes).type
break
}

return {
type: new GraphQLInputObjectType({
name: _.camelCase(`${namespace} ${selector} ${key}QueryList`),
name: createTypeName(`${namespace} ${selector} ${key}QueryList`),
fields: {
...typeFields(headType),
in: { type: new GraphQLList(inType) },
Expand All @@ -93,7 +100,7 @@ const inferGraphQLInputFields = (exports.inferGraphQLInputFields = (
case `boolean`:
return {
type: new GraphQLInputObjectType({
name: _.camelCase(`${namespace} ${selector} ${key}QueryBoolean`),
name: createTypeName(`${namespace} ${selector} ${key}QueryBoolean`),
fields: {
...typeFields(`boolean`),
},
Expand All @@ -102,7 +109,7 @@ const inferGraphQLInputFields = (exports.inferGraphQLInputFields = (
case `string`:
return {
type: new GraphQLInputObjectType({
name: _.camelCase(`${namespace} ${selector} ${key}QueryString`),
name: createTypeName(`${namespace} ${selector} ${key}QueryString`),
fields: {
...typeFields(`string`),
},
Expand All @@ -111,15 +118,15 @@ const inferGraphQLInputFields = (exports.inferGraphQLInputFields = (
case `object`:
return {
type: new GraphQLInputObjectType({
name: _.camelCase(`${namespace} ${selector} ${key}InputObject`),
name: createTypeName(`${namespace} ${selector} ${key}InputObject`),
fields: inferInputObjectStructureFromNodes(nodes, key, namespace),
}),
}
case `number`:
if (value % 1 === 0) {
return {
type: new GraphQLInputObjectType({
name: _.camelCase(`${namespace} ${selector} ${key}QueryNumber`),
name: createTypeName(`${namespace} ${selector} ${key}QueryNumber`),
fields: {
...typeFields(`int`),
},
Expand All @@ -128,7 +135,7 @@ const inferGraphQLInputFields = (exports.inferGraphQLInputFields = (
} else {
return {
type: new GraphQLInputObjectType({
name: _.camelCase(`${namespace} ${selector} ${key}QueryFloat`),
name: createTypeName(`${namespace} ${selector} ${key}QueryFloat`),
fields: {
...typeFields(`float`),
},
Expand Down
13 changes: 1 addition & 12 deletions packages/gatsby/lib/schema/infer-graphql-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,7 @@ const isRelativeUrl = require(`is-relative-url`)
const { store, getNode, getNodes } = require(`../redux`)
const { addPageDependency } = require(`../redux/actions/add-page-dependency`)
const { extractFieldExamples } = require(`./data-tree-utils`)

const seenNames = {}
const createTypeName = name => {
const cameledName = _.camelCase(name)
if (seenNames[cameledName]) {
seenNames[cameledName] += 1
return `${cameledName}_${seenNames[cameledName]}`
} else {
seenNames[cameledName] = 1
return cameledName
}
}
const createTypeName = require(`./create-type-name`)

const inferGraphQLType = ({ value, selector, fieldName, ...otherArgs }) => {
const newSelector = selector ? [selector, fieldName].join(`.`) : fieldName
Expand Down

0 comments on commit 7b45d92

Please sign in to comment.