@@ -23,8 +23,8 @@ import * as debugFactory from "debug";
2323type mixed = Record < string , any > | string | number | boolean | undefined | null ;
2424
2525export interface FieldsByTypeName {
26- [ str : string ] : {
27- [ str : string ] : ResolveTree ;
26+ [ typeName : string ] : {
27+ [ responseName : string ] : ResolveTree ;
2828 } ;
2929}
3030
@@ -350,17 +350,32 @@ function getType(
350350export function simplifyParsedResolveInfoFragmentWithType (
351351 parsedResolveInfoFragment : ResolveTree ,
352352 type : GraphQLType
353- ) {
353+ ) : ResolveTree & { fields : { [ responseName : string ] : ResolveTree } } {
354354 const { fieldsByTypeName } = parsedResolveInfoFragment ;
355- const fields = { } ;
355+ const fields : { [ responseName : string ] : ResolveTree } = Object . create ( null ) ;
356356 const strippedType = getNamedType ( type ) ;
357357 if ( isCompositeType ( strippedType ) ) {
358- Object . assign ( fields , fieldsByTypeName [ strippedType . name ] ) ;
358+ if ( fieldsByTypeName [ strippedType . name ] ) {
359+ Object . assign ( fields , fieldsByTypeName [ strippedType . name ] ) ;
360+ }
359361 if ( strippedType instanceof GraphQLObjectType ) {
360362 const objectType : GraphQLObjectType = strippedType ;
361- // GraphQL ensures that the subfields cannot clash, so it's safe to simply overwrite them
363+ // GraphQL ensures that the subfields cannot clash, so it's safe to
364+ // simply merge them.
362365 for ( const anInterface of objectType . getInterfaces ( ) ) {
363- Object . assign ( fields , fieldsByTypeName [ anInterface . name ] ) ;
366+ const interfaceFields = fieldsByTypeName [ anInterface . name ] ;
367+ if ( ! interfaceFields ) continue ;
368+ for ( const responseName of Object . keys ( interfaceFields ) ) {
369+ const interfaceField = interfaceFields [ responseName ] ;
370+ if ( fields [ responseName ] ) {
371+ fields [ responseName ] = recursiveMerge (
372+ fields [ responseName ] ,
373+ interfaceField
374+ ) ;
375+ } else {
376+ fields [ responseName ] = interfaceField ;
377+ }
378+ }
364379 }
365380 }
366381 }
@@ -370,6 +385,37 @@ export function simplifyParsedResolveInfoFragmentWithType(
370385 } ;
371386}
372387
388+ function recursiveMerge ( treeA : ResolveTree , treeB : ResolveTree ) : ResolveTree {
389+ const result : ResolveTree = {
390+ // GraphQL ensures that the subfields cannot clash, so the name, alias and
391+ // args will definitely line up, and the fieldsByTypeName can be merged.
392+ ...treeA ,
393+ fieldsByTypeName : Object . create ( null ) ,
394+ } ;
395+
396+ for ( const tree of [ treeA , treeB ] ) {
397+ for ( const typeName of Object . keys ( tree . fieldsByTypeName ) ) {
398+ if ( ! result . fieldsByTypeName [ typeName ] ) {
399+ result . fieldsByTypeName [ typeName ] = Object . create ( null ) ;
400+ }
401+ const targetFields = result . fieldsByTypeName [ typeName ] ;
402+ const sourceFields = tree . fieldsByTypeName [ typeName ] ;
403+ for ( const responseName of Object . keys ( sourceFields ) ) {
404+ if ( ! targetFields [ responseName ] ) {
405+ targetFields [ responseName ] = sourceFields [ responseName ] ;
406+ } else {
407+ targetFields [ responseName ] = recursiveMerge (
408+ targetFields [ responseName ] ,
409+ sourceFields [ typeName ]
410+ ) ;
411+ }
412+ }
413+ }
414+ }
415+
416+ return result ;
417+ }
418+
373419export const parse = parseResolveInfo ;
374420export const simplify = simplifyParsedResolveInfoFragmentWithType ;
375421export const getAlias = getAliasFromResolveInfo ;
0 commit comments