From 4d7f4b306e72d68d7563b17d45200f39bada1892 Mon Sep 17 00:00:00 2001 From: Vladimir Razuvaev Date: Fri, 4 Dec 2020 21:00:13 +0700 Subject: [PATCH] fix(gatsby): print childOf directive for implicit child fields --- .../__tests__/__snapshots__/print.js.snap | 12 +++++ packages/gatsby/src/schema/__tests__/print.js | 17 +++++- packages/gatsby/src/schema/schema.js | 52 ++++++++++++------- 3 files changed, 61 insertions(+), 20 deletions(-) diff --git a/packages/gatsby/src/schema/__tests__/__snapshots__/print.js.snap b/packages/gatsby/src/schema/__tests__/__snapshots__/print.js.snap index 81b5bdfe03dca..d63f0231ccec2 100644 --- a/packages/gatsby/src/schema/__tests__/__snapshots__/print.js.snap +++ b/packages/gatsby/src/schema/__tests__/__snapshots__/print.js.snap @@ -120,6 +120,10 @@ input Baz { qux: Boolean } +type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer { + bar: String +} + type Test implements Node @dontInfer { foo: Int }" @@ -266,6 +270,10 @@ type OneMoreTest implements Node @dontInfer { union ThisOrThat = AnotherTest | OneMoreTest +type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer { + bar: String +} + type Test implements Node @dontInfer { foo: Int }" @@ -423,6 +431,10 @@ input Baz { qux: Boolean } +type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer { + bar: String +} + type Test implements Node @dontInfer { foo: Int }" diff --git a/packages/gatsby/src/schema/__tests__/print.js b/packages/gatsby/src/schema/__tests__/print.js index dfccfddac0b6b..9b4a31610a876 100644 --- a/packages/gatsby/src/schema/__tests__/print.js +++ b/packages/gatsby/src/schema/__tests__/print.js @@ -2,6 +2,8 @@ const { build } = require(`..`) import { buildObjectType } from "../types/type-builders" const { store } = require(`../../redux`) const { actions } = require(`../../redux/actions/restricted`) +const { actions: publicActions } = require(`../../redux/actions/public`) +const { createParentChildLink } = publicActions const { printTypeDefinitions } = actions jest.mock(`fs-extra`) @@ -41,14 +43,25 @@ jest.spyOn(global.Date.prototype, `toISOString`).mockReturnValue(`2019-01-01`) describe(`Print type definitions`, () => { beforeEach(() => { store.dispatch({ type: `DELETE_CACHE` }) - const node = { + const node1 = { id: `test1`, internal: { type: `Test`, }, + children: [], foo: 26, } - store.dispatch({ type: `CREATE_NODE`, payload: { ...node } }) + const node2 = { + id: `test2`, + parent: `test1`, + internal: { + type: `FooChild`, + }, + bar: `bar`, + } + store.dispatch({ type: `CREATE_NODE`, payload: { ...node1 } }) + store.dispatch({ type: `CREATE_NODE`, payload: { ...node2 } }) + createParentChildLink({ parent: node1, child: node2 }) const typeDefs = [] typeDefs.push(` type AnotherTest implements Node & ITest { diff --git a/packages/gatsby/src/schema/schema.js b/packages/gatsby/src/schema/schema.js index 00d1caee63e06..69365d9184131 100644 --- a/packages/gatsby/src/schema/schema.js +++ b/packages/gatsby/src/schema/schema.js @@ -146,6 +146,9 @@ const updateSchemaComposer = async ({ inferenceMetadata, parentSpan: activity.span, }) + addInferredChildOfExtensions({ + schemaComposer, + }) activity.end() activity = report.phantomActivity(`Processing types`, { @@ -202,11 +205,6 @@ const processTypeComposer = async ({ if (typeComposer.hasInterface(`Node`)) { await addNodeInterfaceFields({ schemaComposer, typeComposer, parentSpan }) - await addImplicitConvenienceChildrenFields({ - schemaComposer, - typeComposer, - parentSpan, - }) } await determineSearchableFields({ schemaComposer, @@ -999,15 +997,26 @@ const addConvenienceChildrenFields = ({ schemaComposer }) => { }) } -const addImplicitConvenienceChildrenFields = ({ - schemaComposer, - typeComposer, -}) => { +const addInferredChildOfExtensions = ({ schemaComposer }) => { + schemaComposer.forEach(typeComposer => { + if ( + typeComposer instanceof ObjectTypeComposer && + typeComposer.hasInterface(`Node`) + ) { + addInferredChildOfExtension({ + schemaComposer, + typeComposer, + }) + } + }) +} + +const addInferredChildOfExtension = ({ schemaComposer, typeComposer }) => { const shouldInfer = typeComposer.getExtension(`infer`) - // In Gatsby v3, when `@dontInfer` is set, children fields will not be - // created for parent-child relations set by plugins with + // In Gatsby v3, when `@dontInfer` is set, `@childOf` extension will not be + // automatically created for parent-child relations set by plugins with // `createParentChildLink`. With `@dontInfer`, only parent-child - // relations explicitly set with the `childOf` extension will be added. + // relations explicitly set with the `@childOf` extension will be added. // if (shouldInfer === false) return const parentTypeName = typeComposer.getTypeName() @@ -1017,10 +1026,11 @@ const addImplicitConvenienceChildrenFields = ({ Object.keys(childNodesByType).forEach(typeName => { // Adding children fields to types with the `@dontInfer` extension is deprecated - if (shouldInfer === false) { - const childTypeComposer = schemaComposer.getAnyTC(typeName) - const childOfExtension = childTypeComposer.getExtension(`childOf`) + const childTypeComposer = schemaComposer.getAnyTC(typeName) + let childOfExtension = childTypeComposer.getExtension(`childOf`) + if (shouldInfer === false) { + // Adding children fields to types with the `@dontInfer` extension is deprecated // Only warn when the parent-child relation has not been explicitly set with if ( !childOfExtension || @@ -1046,9 +1056,15 @@ const addImplicitConvenienceChildrenFields = ({ ) } } - - typeComposer.addFields(createChildrenField(typeName)) - typeComposer.addFields(createChildField(typeName)) + // Set `@childOf` extension automatically + // This will cause convenience children fields like `childImageSharp` + // to be added in `addConvenienceChildrenFields` method. + // Also required for proper printing of the `@childOf` directive in the snapshot plugin + if (!childOfExtension?.types) { + childOfExtension = { types: [] } + } + childOfExtension.types.push(parentTypeName) + childTypeComposer.setExtension(`childOf`, childOfExtension) }) }