diff --git a/packages/gatsby/lib/schema/__tests__/infer-graphql-input-type.js b/packages/gatsby/lib/schema/__tests__/infer-graphql-input-type.js index f5b4fae571217..d6f8b49128e1f 100644 --- a/packages/gatsby/lib/schema/__tests__/infer-graphql-input-type.js +++ b/packages/gatsby/lib/schema/__tests__/infer-graphql-input-type.js @@ -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`, @@ -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())) }) diff --git a/packages/gatsby/lib/schema/create-type-name.js b/packages/gatsby/lib/schema/create-type-name.js new file mode 100644 index 0000000000000..1a28ea6ca90ee --- /dev/null +++ b/packages/gatsby/lib/schema/create-type-name.js @@ -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 + } +} diff --git a/packages/gatsby/lib/schema/infer-graphql-input-fields.js b/packages/gatsby/lib/schema/infer-graphql-input-fields.js index aa03e2a433e11..dde2ec6cf11ff 100644 --- a/packages/gatsby/lib/schema/infer-graphql-input-fields.js +++ b/packages/gatsby/lib/schema/infer-graphql-input-fields.js @@ -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, @@ -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` @@ -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) }, @@ -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`), }, @@ -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`), }, @@ -111,7 +118,7 @@ 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), }), } @@ -119,7 +126,7 @@ const inferGraphQLInputFields = (exports.inferGraphQLInputFields = ( if (value % 1 === 0) { return { type: new GraphQLInputObjectType({ - name: _.camelCase(`${namespace} ${selector} ${key}QueryNumber`), + name: createTypeName(`${namespace} ${selector} ${key}QueryNumber`), fields: { ...typeFields(`int`), }, @@ -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`), }, diff --git a/packages/gatsby/lib/schema/infer-graphql-type.js b/packages/gatsby/lib/schema/infer-graphql-type.js index a0c73fa2315f6..e0ae83f871bf0 100644 --- a/packages/gatsby/lib/schema/infer-graphql-type.js +++ b/packages/gatsby/lib/schema/infer-graphql-type.js @@ -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