Skip to content

Commit

Permalink
fix(gatsby): print childOf directive for implicit child fields (#28483)
Browse files Browse the repository at this point in the history
* fix(gatsby): print childOf directive for implicit child fields

* fix comments

* address review comments

* be more defensive

* Revert "be more defensive"

This reverts commit e139486

* fix duplicate types printing in `childOf`

* fix invalid deprecation warning when mimeTypes is set
  • Loading branch information
vladar committed Dec 23, 2020
1 parent 3af7182 commit 146b197
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 44 deletions.
28 changes: 28 additions & 0 deletions packages/gatsby/src/schema/__tests__/__snapshots__/print.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ input Baz {
qux: Boolean
}
type BarChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
bar: String
}
type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
bar: String
}
type Test implements Node @dontInfer {
foo: Int
}"
Expand Down Expand Up @@ -148,6 +156,10 @@ type Nested {
input Baz {
qux: Boolean
}
type BarChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
bar: String
}"
`;

Expand Down Expand Up @@ -266,6 +278,14 @@ type OneMoreTest implements Node @dontInfer {
union ThisOrThat = AnotherTest | OneMoreTest
type BarChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
bar: String
}
type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
bar: String
}
type Test implements Node @dontInfer {
foo: Int
}"
Expand Down Expand Up @@ -423,6 +443,14 @@ input Baz {
qux: Boolean
}
type BarChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
bar: String
}
type FooChild implements Node @childOf(types: [\\"Test\\"]) @dontInfer {
bar: String
}
type Test implements Node @dontInfer {
foo: Int
}"
Expand Down
44 changes: 42 additions & 2 deletions packages/gatsby/src/schema/__tests__/print.js
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down Expand Up @@ -41,14 +43,35 @@ 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`,
}
const node3 = {
id: `test3`,
parent: `test1`,
internal: {
type: `BarChild`,
},
bar: `bar`,
}
store.dispatch({ type: `CREATE_NODE`, payload: { ...node1 } })
store.dispatch({ type: `CREATE_NODE`, payload: { ...node2 } })
store.dispatch({ type: `CREATE_NODE`, payload: { ...node3 } })
createParentChildLink({ parent: node1, child: node2 })
createParentChildLink({ parent: node1, child: node3 })
const typeDefs = []
typeDefs.push(`
type AnotherTest implements Node & ITest {
Expand Down Expand Up @@ -96,6 +119,18 @@ describe(`Print type definitions`, () => {
types: [`OneMoreTest`],
},
},
}),
buildObjectType({
name: `BarChild`,
fields: {
id: `ID!`,
},
interfaces: [`Node`],
extensions: {
childOf: {
types: [`Test`],
},
},
})
)
store.dispatch({
Expand All @@ -108,6 +143,11 @@ describe(`Print type definitions`, () => {
payload: typeDefs[1],
plugin: { name: `gatsby-plugin-another-test` },
})
store.dispatch({
type: `CREATE_TYPES`,
payload: typeDefs[2],
plugin: { name: `gatsby-plugin-another-test` },
})
})

it(`saves type definitions to default file`, async () => {
Expand Down
18 changes: 18 additions & 0 deletions packages/gatsby/src/schema/extensions/__tests__/child-relations.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,24 @@ describe(`Define parent-child relationships with field extensions`, () => {
)
})

it(`does not show deprecation warning for inferred child fields`, async () => {
dispatch(
createTypes(`
type Parent implements Node @dontInfer @mimeTypes(types: ["application/listenup"]) {
id: ID!
}
type Child implements Node @childOf(mimeTypes: ["application/listenup"]) {
id: ID!
}
type AnotherChild implements Node @childOf(types: ["Parent"]) {
id: ID!
}
`)
)
await buildSchema()
expect(report.warn).toBeCalledTimes(0)
})

it(`adds children[Field] field to parent type with childOf extension`, async () => {
dispatch(
createTypes(`
Expand Down
116 changes: 74 additions & 42 deletions packages/gatsby/src/schema/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ const updateSchemaComposer = async ({
inferenceMetadata,
parentSpan: activity.span,
})
addInferredChildOfExtensions({
schemaComposer,
})
activity.end()

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

if (typeComposer.hasInterface(`Node`)) {
await addNodeInterfaceFields({ schemaComposer, typeComposer, parentSpan })
await addImplicitConvenienceChildrenFields({
schemaComposer,
typeComposer,
parentSpan,
})
}
await determineSearchableFields({
schemaComposer,
Expand Down Expand Up @@ -999,15 +997,42 @@ const addConvenienceChildrenFields = ({ schemaComposer }) => {
})
}

const addImplicitConvenienceChildrenFields = ({
schemaComposer,
typeComposer,
}) => {
const isExplicitChild = ({ typeComposer, childTypeComposer }) => {
if (!childTypeComposer.hasExtension(`childOf`)) {
return false
}
const childOfExtension = childTypeComposer.getExtension(`childOf`)
const { types: parentMimeTypes = [] } =
typeComposer.getExtension(`mimeTypes`) ?? {}

return (
childOfExtension?.types?.includes(typeComposer.getTypeName()) ||
childOfExtension?.mimeTypes?.some(mimeType =>
parentMimeTypes.includes(mimeType)
)
)
}

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()
Expand All @@ -1016,39 +1041,46 @@ const addImplicitConvenienceChildrenFields = ({
const childNodesByType = groupChildNodesByType({ nodes })

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`)

// Only warn when the parent-child relation has not been explicitly set with
if (
!childOfExtension ||
!childOfExtension.types.includes(parentTypeName)
) {
const childField = fieldNames.convenienceChild(typeName)
const childrenField = fieldNames.convenienceChildren(typeName)
const childOfTypes = (childOfExtension?.types ?? [])
.concat(parentTypeName)
.map(name => `"${name}"`)
.join(`,`)

report.warn(
`Deprecation warning: ` +
`In Gatsby v3 fields \`${parentTypeName}.${childField}\` and \`${parentTypeName}.${childrenField}\` ` +
`will not be added automatically because ` +
`type \`${typeName}\` does not explicitly list type \`${parentTypeName}\` in \`childOf\` extension.\n` +
`Add the following type definition to fix this:\n\n` +
` type ${typeName} implements Node @childOf(types: [${childOfTypes}]) {\n` +
` id: ID!\n` +
` }\n\n` +
`https://www.gatsbyjs.com/docs/actions/#createTypes`
)
}
if (isExplicitChild({ typeComposer, childTypeComposer })) {
return
}
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 `childOf` directive
const childField = fieldNames.convenienceChild(typeName)
const childrenField = fieldNames.convenienceChildren(typeName)
const childOfTypes = (childOfExtension?.types ?? [])
.concat(parentTypeName)
.map(name => `"${name}"`)
.join(`,`)

typeComposer.addFields(createChildrenField(typeName))
typeComposer.addFields(createChildField(typeName))
report.warn(
`Deprecation warning: ` +
`In Gatsby v3 fields \`${parentTypeName}.${childField}\` and \`${parentTypeName}.${childrenField}\` ` +
`will not be added automatically because ` +
`type \`${typeName}\` does not explicitly list type \`${parentTypeName}\` in \`childOf\` extension.\n` +
`Add the following type definition to fix this:\n\n` +
` type ${typeName} implements Node @childOf(types: [${childOfTypes}]) {\n` +
` id: ID!\n` +
` }\n\n` +
`https://www.gatsbyjs.com/docs/actions/#createTypes`
)
}
// 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) {
childOfExtension = {}
}
if (!childOfExtension.types) {
childOfExtension.types = []
}
childOfExtension.types.push(parentTypeName)
childTypeComposer.setExtension(`childOf`, childOfExtension)
})
}

Expand Down

0 comments on commit 146b197

Please sign in to comment.