From a17c1d36e949bb66e5ab8c630380c8472fd24855 Mon Sep 17 00:00:00 2001 From: LeKoArts Date: Thu, 5 Jul 2018 22:06:10 +0200 Subject: [PATCH 1/5] Add first draft for working sorting on Tags with Prismic.io data by changing the tests --- .../infer-graphql-input-type-test.js | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js index 07bdb94fcde34..f4d80730bbee3 100644 --- a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js +++ b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js @@ -143,6 +143,74 @@ describe(`GraphQL Input args`, () => { blue: 10010, circle: `happy`, }, + data: { + tags: [ + { + tag: { + document: [ + { + data: { + tag: `Design System`, + }, + }, + ], + }, + }, + ], + }, + }, + { + index: 3, + name: `Prismic Stress Test`, + date: `2018-07-04T18:34:44+0000`, + data: { + title: { + text: `Create your design system with Gatsby`, + }, + body: [ + { + slice_type: `text`, + primary: { + text: { + text: `Content of this slice`, + }, + }, + }, + ], + category: { + document: [ + { + data: { + category: `Coding`, + }, + }, + ], + }, + tags: [ + { + tag: { + document: [ + { + data: { + tag: `Gatsby`, + }, + }, + ], + }, + }, + { + tag: { + document: [ + { + data: { + tag: `Design System`, + }, + }, + ], + }, + }, + ], + }, }, ] @@ -638,6 +706,21 @@ describe(`GraphQL Input args`, () => { expect(result).toMatchSnapshot() }) + + it(`can filter for Prismic tags`, async () => { + let result = await queryResult( + nodes, + ` + { + allNode(filter: {data: {tags: {in: {tag: {document: {data: {tag: {eq: "Gatsby"}}}}}}}}) { + edges { node { name }} + } + } + ` + ) + expect(result.errors).not.toBeDefined() + expect(result.data.allNode.edges[0].node.name).toEqual(`Prismic Stress Test`) + }) }) describe(`filtering on linked nodes`, () => { From b4aaf24f08a75c2076ae0a1f590f9621a25be739 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Sat, 7 Jul 2018 02:29:28 +0200 Subject: [PATCH 2/5] update test fixture, so it doesn't cause failure of unrelated tests, but still enable to test added functionality --- .../infer-graphql-input-type-test.js | 107 ++++++++---------- 1 file changed, 47 insertions(+), 60 deletions(-) diff --git a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js index f4d80730bbee3..9bd55cafdb153 100644 --- a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js +++ b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js @@ -126,23 +126,6 @@ describe(`GraphQL Input args`, () => { circle: `happy`, }, boolean: false, - }, - { - index: 2, - name: `The Mad Wax`, - hair: 0, - date: `2006-07-29T22:39:53.000Z`, - anotherKey: { - withANested: { - nestedKey: `bar`, - }, - }, - frontmatter: { - date: `2006-07-22T22:39:53.000Z`, - title: `The world of shave and adventure`, - blue: 10010, - circle: `happy`, - }, data: { tags: [ { @@ -152,6 +135,7 @@ describe(`GraphQL Input args`, () => { data: { tag: `Design System`, }, + number: 3, }, ], }, @@ -160,32 +144,22 @@ describe(`GraphQL Input args`, () => { }, }, { - index: 3, - name: `Prismic Stress Test`, - date: `2018-07-04T18:34:44+0000`, - data: { - title: { - text: `Create your design system with Gatsby`, - }, - body: [ - { - slice_type: `text`, - primary: { - text: { - text: `Content of this slice`, - }, - }, - }, - ], - category: { - document: [ - { - data: { - category: `Coding`, - }, - }, - ], + index: 2, + name: `The Mad Wax`, + hair: 0, + date: `2006-07-29T22:39:53.000Z`, + anotherKey: { + withANested: { + nestedKey: `bar`, }, + }, + frontmatter: { + date: `2006-07-22T22:39:53.000Z`, + title: `The world of shave and adventure`, + blue: 10010, + circle: `happy`, + }, + data: { tags: [ { tag: { @@ -205,6 +179,7 @@ describe(`GraphQL Input args`, () => { data: { tag: `Design System`, }, + number: 5, }, ], }, @@ -532,18 +507,45 @@ describe(`GraphQL Input args`, () => { expect(result.data.allNode.edges[0].node.name).toEqual(`The Mad Wax`) }) - it(`handles the glob operator`, async () => { + it(`handles the in operator for array of objects`, async () => { let result = await queryResult( nodes, ` { - allNode(limit: 10, filter: {name: { glob: "*Wax" }}) { - edges { node { name }} + test1:allNode(filter: {data: {tags: {in: {tag: {document: {in: {data: {tag: {eq: "Gatsby"}}}}}}}}}) { + edges { node { index }} + } + test2:allNode(filter: {data: {tags: {in: {tag: {document: {in: {data: {tag: {eq: "Design System"}}}}}}}}}) { + edges { node { index }} + } + test3:allNode(filter: {data: {tags: {in: {tag: {document: {in: {number: {lt: 4}}}}}}}}) { + edges { node { index }} } } ` ) expect(result.errors).not.toBeDefined() + expect(result.data.test1.edges.length).toEqual(1) + expect(result.data.test1.edges[0].node.index).toEqual(2) + expect(result.data.test2.edges.length).toEqual(2) + expect(result.data.test2.edges[0].node.index).toEqual(1) + expect(result.data.test2.edges[1].node.index).toEqual(2) + expect(result.data.test3.edges.length).toEqual(1) + expect(result.data.test3.edges[0].node.index).toEqual(1) + }) + + it(`handles the glob operator`, async () => { + let result = await queryResult( + nodes, + ` + { + allNode(limit: 10, filter: {name: { glob: "*Wax" }}) { + edges { node { name }} + } + } + ` + ) + expect(result.errors).not.toBeDefined() expect(result.data.allNode.edges.length).toEqual(2) expect(result.data.allNode.edges[0].node.name).toEqual(`The Mad Wax`) }) @@ -706,21 +708,6 @@ describe(`GraphQL Input args`, () => { expect(result).toMatchSnapshot() }) - - it(`can filter for Prismic tags`, async () => { - let result = await queryResult( - nodes, - ` - { - allNode(filter: {data: {tags: {in: {tag: {document: {data: {tag: {eq: "Gatsby"}}}}}}}}) { - edges { node { name }} - } - } - ` - ) - expect(result.errors).not.toBeDefined() - expect(result.data.allNode.edges[0].node.name).toEqual(`Prismic Stress Test`) - }) }) describe(`filtering on linked nodes`, () => { From 0515810c60bc49d4685bb6f113a66baeef57b612 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Sat, 7 Jul 2018 02:30:03 +0200 Subject: [PATCH 3/5] properly support "in" operator for array of objects --- packages/gatsby/src/schema/run-sift.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/gatsby/src/schema/run-sift.js b/packages/gatsby/src/schema/run-sift.js index be8fa5fb47e2f..8424910f8c0a0 100644 --- a/packages/gatsby/src/schema/run-sift.js +++ b/packages/gatsby/src/schema/run-sift.js @@ -43,7 +43,7 @@ module.exports = ({ const siftifyArgs = object => { const newObject = {} _.each(object, (v, k) => { - if (_.isObject(v) && !_.isArray(v)) { + if (_.isPlainObject(v)) { newObject[k] = siftifyArgs(v) } else { // Compile regex first. @@ -53,6 +53,8 @@ module.exports = ({ const Minimatch = require(`minimatch`).Minimatch const mm = new Minimatch(v) newObject[`$regex`] = mm.makeRe() + } else if (k === `in` && Array.isArray(v) && _.isPlainObject(v[0])) { + newObject[`$elemMatch`] = siftifyArgs(v[0]) } else { newObject[`$${k}`] = v } @@ -64,7 +66,7 @@ module.exports = ({ // Build an object that excludes the innermost leafs, // this avoids including { eq: x } when resolving fields. function extractFieldsToSift(prekey, key, preobj, obj, val) { - if (_.isObject(val) && !_.isArray(val)) { + if (_.isPlainObject(val)) { _.forEach((val: any), (v, k) => { preobj[prekey] = obj extractFieldsToSift(key, k, obj, {}, v) From 1fd7509a5adfac3dc48f47ef8247b77360274d62 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Mon, 9 Jul 2018 16:22:30 +0200 Subject: [PATCH 4/5] change in to elemMatch --- .../infer-graphql-input-type-test.js | 6 +++--- .../src/schema/infer-graphql-input-fields.js | 19 +++++++++++++++---- packages/gatsby/src/schema/run-sift.js | 5 +++-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js index 37d38e913eced..e829f9e043dab 100644 --- a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js +++ b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js @@ -553,13 +553,13 @@ describe(`GraphQL Input args`, () => { nodes, ` { - test1:allNode(filter: {data: {tags: {in: {tag: {document: {in: {data: {tag: {eq: "Gatsby"}}}}}}}}}) { + test1:allNode(filter: {data: {tags: {elemMatch: {tag: {document: {elemMatch: {data: {tag: {eq: "Gatsby"}}}}}}}}}) { edges { node { index }} } - test2:allNode(filter: {data: {tags: {in: {tag: {document: {in: {data: {tag: {eq: "Design System"}}}}}}}}}) { + test2:allNode(filter: {data: {tags: {elemMatch: {tag: {document: {elemMatch: {data: {tag: {eq: "Design System"}}}}}}}}}) { edges { node { index }} } - test3:allNode(filter: {data: {tags: {in: {tag: {document: {in: {number: {lt: 4}}}}}}}}) { + test3:allNode(filter: {data: {tags: {elemMatch: {tag: {document: {elemMatch: {number: {lt: 4}}}}}}}}) { edges { node { index }} } } diff --git a/packages/gatsby/src/schema/infer-graphql-input-fields.js b/packages/gatsby/src/schema/infer-graphql-input-fields.js index c67f3dfa9c7c0..c8cdbc2e8c5b5 100644 --- a/packages/gatsby/src/schema/infer-graphql-input-fields.js +++ b/packages/gatsby/src/schema/infer-graphql-input-fields.js @@ -125,13 +125,24 @@ function inferGraphQLInputFields({ ) } + let fields + if (headType === `object`) { + fields = { + elemMatch: { + type: inType, + }, + } + } else { + fields = { + ...typeFields(headType), + in: { type: new GraphQLList(inType) }, + } + } + return { type: new GraphQLInputObjectType({ name: createTypeName(`${prefix}QueryList`), - fields: { - ...typeFields(headType), - in: { type: new GraphQLList(inType) }, - }, + fields, }), } } diff --git a/packages/gatsby/src/schema/run-sift.js b/packages/gatsby/src/schema/run-sift.js index 8424910f8c0a0..5139b2977c8de 100644 --- a/packages/gatsby/src/schema/run-sift.js +++ b/packages/gatsby/src/schema/run-sift.js @@ -44,6 +44,9 @@ module.exports = ({ const newObject = {} _.each(object, (v, k) => { if (_.isPlainObject(v)) { + if (k === `elemMatch`) { + k = `$elemMatch` + } newObject[k] = siftifyArgs(v) } else { // Compile regex first. @@ -53,8 +56,6 @@ module.exports = ({ const Minimatch = require(`minimatch`).Minimatch const mm = new Minimatch(v) newObject[`$regex`] = mm.makeRe() - } else if (k === `in` && Array.isArray(v) && _.isPlainObject(v[0])) { - newObject[`$elemMatch`] = siftifyArgs(v[0]) } else { newObject[`$${k}`] = v } From 3e0839df3eed10f5f7ef9999a14efd460ea939ab Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Tue, 10 Jul 2018 18:57:15 +0200 Subject: [PATCH 5/5] adjust schema for fields created by setFieldsOnGraphQLNodeType --- .../infer-graphql-input-fields-from-fields.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/gatsby/src/schema/infer-graphql-input-fields-from-fields.js b/packages/gatsby/src/schema/infer-graphql-input-fields-from-fields.js index b6f05874fb906..d22d987f34928 100644 --- a/packages/gatsby/src/schema/infer-graphql-input-fields-from-fields.js +++ b/packages/gatsby/src/schema/infer-graphql-input-fields-from-fields.js @@ -148,12 +148,21 @@ function convertToInputFilter( const innerFilter = convertToInputFilter(`${prefix}ListElem`, innerType) const innerFields = innerFilter ? innerFilter.getFields() : {} - return new GraphQLInputObjectType({ - name: createTypeName(`${prefix}QueryList`), - fields: { + let fields + if (innerType instanceof GraphQLInputObjectType) { + fields = { + elemMatch: { type: innerFilter }, + } + } else { + fields = { ...innerFields, in: { type: new GraphQLList(innerType) }, - }, + } + } + + return new GraphQLInputObjectType({ + name: createTypeName(`${prefix}QueryList`), + fields, }) } else if (type instanceof GraphQLNonNull) { return convertToInputFilter(prefix, type.ofType)