From 302aa264714b240fd3f5fbfb29e1993f15d64630 Mon Sep 17 00:00:00 2001 From: stefanprobst Date: Mon, 14 Oct 2019 23:16:33 +0200 Subject: [PATCH] fix(gatsby): Extend fields when merging types (#18500) --- .../src/schema/__tests__/build-schema.js | 27 +++++++++++++++ packages/gatsby/src/schema/schema.js | 33 ++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/packages/gatsby/src/schema/__tests__/build-schema.js b/packages/gatsby/src/schema/__tests__/build-schema.js index e5e36fb251280..a8477e2d5cd59 100644 --- a/packages/gatsby/src/schema/__tests__/build-schema.js +++ b/packages/gatsby/src/schema/__tests__/build-schema.js @@ -814,6 +814,33 @@ describe(`Build schema`, () => { ) }) + it(`extends fieldconfigs when merging types`, async () => { + createTypes( + buildObjectType({ + name: `Mdx`, + interfaces: [`Node`], + fields: { + body: { + type: `String`, + resolve: () => `Mdx!`, + }, + }, + }) + ) + createTypes(` + type Mdx implements Node { + body: String! + } + `) + + const schema = await buildSchema() + const fields = schema.getType(`Mdx`).getFields() + + expect(fields.body.type.toString()).toBe(`String!`) + expect(typeof fields.body.resolve).toBe(`function`) + expect(fields.body.resolve()).toBe(`Mdx!`) + }) + it(`displays error message for reserved Node interface`, () => { const typeDefs = [ `interface Node { foo: Boolean }`, diff --git a/packages/gatsby/src/schema/schema.js b/packages/gatsby/src/schema/schema.js index 8e1b17643711c..e8d7a1e602447 100644 --- a/packages/gatsby/src/schema/schema.js +++ b/packages/gatsby/src/schema/schema.js @@ -7,6 +7,8 @@ const { parse, GraphQLNonNull, GraphQLList, + GraphQLObjectType, + GraphQLInterfaceType, } = require(`graphql`) const { ObjectTypeComposer, @@ -15,6 +17,7 @@ const { InputTypeComposer, ScalarTypeComposer, EnumTypeComposer, + defineFieldMapToConfig, } = require(`graphql-compose`) const apiRunner = require(`../utils/api-runner-node`) @@ -315,11 +318,30 @@ const mergeTypes = ({ plugin.name === `default-site-plugin` || plugin.name === typeOwner ) { - typeComposer.merge(type) + if (type instanceof ObjectTypeComposer) { + mergeFields({ typeComposer, fields: type.getFields() }) + type.getInterfaces().forEach(iface => typeComposer.addInterface(iface)) + } else if (type instanceof InterfaceTypeComposer) { + mergeFields({ typeComposer, fields: type.getFields() }) + } else if (type instanceof GraphQLObjectType) { + mergeFields({ + typeComposer, + fields: defineFieldMapToConfig(type.getFields()), + }) + type.getInterfaces().forEach(iface => typeComposer.addInterface(iface)) + } else if (type instanceof GraphQLInterfaceType) { + mergeFields({ + typeComposer, + fields: defineFieldMapToConfig(type.getFields()), + }) + } + if (isNamedTypeComposer(type)) { typeComposer.extendExtensions(type.getExtensions()) } + addExtensions({ schemaComposer, typeComposer, plugin, createdFrom }) + return true } else { report.warn( @@ -1160,3 +1182,12 @@ const checkQueryableInterfaces = ({ schemaComposer }) => { ) } } + +const mergeFields = ({ typeComposer, fields }) => + Object.entries(fields).forEach(([fieldName, fieldConfig]) => { + if (typeComposer.hasField(fieldName)) { + typeComposer.extendField(fieldName, fieldConfig) + } else { + typeComposer.setField(fieldName, fieldConfig) + } + })