Skip to content

Commit 726ba34

Browse files
committed
fix(gatsby): print childOf directive for implicit child fields
1 parent daeb624 commit 726ba34

File tree

3 files changed

+74
-31
lines changed

3 files changed

+74
-31
lines changed

packages/gatsby/src/schema/__tests__/__snapshots__/print.js.snap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ input Baz {
120120
qux: Boolean
121121
}
122122
123+
type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
124+
bar: String
125+
}
126+
123127
type Test implements Node @dontInfer {
124128
foo: Int
125129
}"
@@ -266,6 +270,10 @@ type OneMoreTest implements Node @dontInfer {
266270
267271
union ThisOrThat = AnotherTest | OneMoreTest
268272
273+
type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
274+
bar: String
275+
}
276+
269277
type Test implements Node @dontInfer {
270278
foo: Int
271279
}"
@@ -423,6 +431,10 @@ input Baz {
423431
qux: Boolean
424432
}
425433
434+
type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
435+
bar: String
436+
}
437+
426438
type Test implements Node @dontInfer {
427439
foo: Int
428440
}"

packages/gatsby/src/schema/__tests__/print.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ const { build } = require(`..`)
22
import { buildObjectType } from "../types/type-builders"
33
const { store } = require(`../../redux`)
44
const { actions } = require(`../../redux/actions/restricted`)
5+
const { actions: publicActions } = require(`../../redux/actions/public`)
6+
const { createParentChildLink } = publicActions
57
const { printTypeDefinitions } = actions
68

79
jest.mock(`fs-extra`)
@@ -41,14 +43,25 @@ jest.spyOn(global.Date.prototype, `toISOString`).mockReturnValue(`2019-01-01`)
4143
describe(`Print type definitions`, () => {
4244
beforeEach(() => {
4345
store.dispatch({ type: `DELETE_CACHE` })
44-
const node = {
46+
const node1 = {
4547
id: `test1`,
4648
internal: {
4749
type: `Test`,
4850
},
51+
children: [],
4952
foo: 26,
5053
}
51-
store.dispatch({ type: `CREATE_NODE`, payload: { ...node } })
54+
const node2 = {
55+
id: `test2`,
56+
parent: `test1`,
57+
internal: {
58+
type: `FooChild`,
59+
},
60+
bar: `bar`,
61+
}
62+
store.dispatch({ type: `CREATE_NODE`, payload: { ...node1 } })
63+
store.dispatch({ type: `CREATE_NODE`, payload: { ...node2 } })
64+
createParentChildLink({ parent: node1, child: node2 })
5265
const typeDefs = []
5366
typeDefs.push(`
5467
type AnotherTest implements Node & ITest {

packages/gatsby/src/schema/schema.js

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ const updateSchemaComposer = async ({
146146
inferenceMetadata,
147147
parentSpan: activity.span,
148148
})
149+
addInferredChildOfExtensions({
150+
schemaComposer,
151+
})
149152
activity.end()
150153

151154
activity = report.phantomActivity(`Processing types`, {
@@ -202,11 +205,6 @@ const processTypeComposer = async ({
202205

203206
if (typeComposer.hasInterface(`Node`)) {
204207
await addNodeInterfaceFields({ schemaComposer, typeComposer, parentSpan })
205-
await addImplicitConvenienceChildrenFields({
206-
schemaComposer,
207-
typeComposer,
208-
parentSpan,
209-
})
210208
}
211209
await determineSearchableFields({
212210
schemaComposer,
@@ -1004,15 +1002,26 @@ const addConvenienceChildrenFields = ({ schemaComposer }) => {
10041002
})
10051003
}
10061004

1007-
const addImplicitConvenienceChildrenFields = ({
1008-
schemaComposer,
1009-
typeComposer,
1010-
}) => {
1005+
const addInferredChildOfExtensions = ({ schemaComposer }) => {
1006+
schemaComposer.forEach(typeComposer => {
1007+
if (
1008+
typeComposer instanceof ObjectTypeComposer &&
1009+
typeComposer.hasInterface(`Node`)
1010+
) {
1011+
addInferredChildOfExtension({
1012+
schemaComposer,
1013+
typeComposer,
1014+
})
1015+
}
1016+
})
1017+
}
1018+
1019+
const addInferredChildOfExtension = ({ schemaComposer, typeComposer }) => {
10111020
const shouldInfer = typeComposer.getExtension(`infer`)
1012-
// In Gatsby v3, when `@dontInfer` is set, children fields will not be
1013-
// created for parent-child relations set by plugins with
1021+
// In Gatsby v3, when `@dontInfer` is set, `@childOf` extension will not be
1022+
// automatically created for parent-child relations set by plugins with
10141023
// `createParentChildLink`. With `@dontInfer`, only parent-child
1015-
// relations explicitly set with the `childOf` extension will be added.
1024+
// relations explicitly set with the `@childOf` extension will be added.
10161025
// if (shouldInfer === false) return
10171026

10181027
const parentTypeName = typeComposer.getTypeName()
@@ -1027,18 +1036,18 @@ const addImplicitConvenienceChildrenFields = ({
10271036
g => g.length
10281037
).length
10291038

1030-
// Adding children fields to types with the `@dontInfer` extension is deprecated
1031-
if (shouldInfer === false) {
1032-
const childTypeComposer = schemaComposer.getAnyTC(typeName)
1033-
const childOfExtension = childTypeComposer.getExtension(`childOf`)
1034-
const many = maxChildCount > 1
1039+
const childTypeComposer = schemaComposer.getAnyTC(typeName)
1040+
let childOfExtension = childTypeComposer.getExtension(`childOf`)
1041+
const many = maxChildCount > 1
10351042

1036-
// Only warn when the parent-child relation has not been explicitly set with
1037-
if (
1038-
!childOfExtension ||
1039-
!childOfExtension.types.includes(parentTypeName) ||
1040-
!childOfExtension.many === many
1041-
) {
1043+
// Only warn when the parent-child relation has not been explicitly set with
1044+
if (
1045+
!childOfExtension ||
1046+
!childOfExtension.types.includes(parentTypeName) ||
1047+
childOfExtension.many !== many
1048+
) {
1049+
// Adding children fields to types with the `@dontInfer` extension is deprecated
1050+
if (shouldInfer === false) {
10421051
const fieldName = many
10431052
? fieldNames.convenienceChildren(typeName)
10441053
: fieldNames.convenienceChild(typeName)
@@ -1052,12 +1061,21 @@ const addImplicitConvenienceChildrenFields = ({
10521061
`\`childOf\` extension will be added.\n`
10531062
)
10541063
}
1055-
}
1056-
1057-
if (maxChildCount > 1) {
1058-
typeComposer.addFields(createChildrenField(typeName))
1059-
} else {
1060-
typeComposer.addFields(createChildField(typeName))
1064+
// Set `@childOf` extension automatically
1065+
// This will cause convenience children fields like `childImageSharp`
1066+
// to be added in `addConvenienceChildrenFields` method.
1067+
// Also required for proper printing of the `@childOf` directive in the snapshot plugin
1068+
if (!childOfExtension) {
1069+
// FIXME: `many` is applied to all parent types equally which seems wrong?
1070+
childOfExtension = { types: [] }
1071+
if (many) {
1072+
childOfExtension.many = many
1073+
}
1074+
}
1075+
if (!childOfExtension.types.includes(parentTypeName)) {
1076+
childOfExtension.types.push(parentTypeName)
1077+
}
1078+
childTypeComposer.setExtension(`childOf`, childOfExtension)
10611079
}
10621080
})
10631081
}

0 commit comments

Comments
 (0)