1- import { ApolloFederation , checkObjectTypeFederationDetails , getBaseType } from '@graphql-codegen/plugin-helpers' ;
1+ import { ApolloFederation , type FederationMeta , getBaseType } from '@graphql-codegen/plugin-helpers' ;
22import { getRootTypeNames } from '@graphql-tools/utils' ;
33import autoBind from 'auto-bind' ;
44import {
@@ -78,13 +78,15 @@ export interface ParsedResolversConfig extends ParsedConfig {
7878 allResolversTypeName : string ;
7979 internalResolversPrefix : string ;
8080 generateInternalResolversIfNeeded : NormalizedGenerateInternalResolversIfNeededConfig ;
81- onlyResolveTypeForInterfaces : boolean ;
8281 directiveResolverMappings : Record < string , string > ;
8382 resolversNonOptionalTypename : ResolversNonOptionalTypenameConfig ;
8483 avoidCheckingAbstractTypesRecursively : boolean ;
8584}
8685
87- type FieldDefinitionPrintFn = ( parentName : string , avoidResolverOptionals : boolean ) => string | null ;
86+ type FieldDefinitionPrintFn = (
87+ parentName : string ,
88+ avoidResolverOptionals : boolean
89+ ) => { value : string | null ; meta : { federation ?: { isResolveReference : boolean } } } ;
8890export interface RootResolver {
8991 content : string ;
9092 generatedResolverTypes : {
@@ -584,20 +586,13 @@ export interface RawResolversConfig extends RawConfig {
584586 internalResolversPrefix ?: string ;
585587 /**
586588 * @type object
587- * @default { __resolveReference: false }
589+ * @default {}
588590 * @description If relevant internal resolvers are set to `true`, the resolver type will only be generated if the right conditions are met.
589591 * Enabling this allows a more correct type generation for the resolvers.
590592 * For example:
591593 * - `__isTypeOf` is generated for implementing types and union members
592- * - `__resolveReference` is generated for federation types that have at least one resolvable `@key` directive
593594 */
594595 generateInternalResolversIfNeeded ?: GenerateInternalResolversIfNeededConfig ;
595- /**
596- * @type boolean
597- * @default false
598- * @description Turning this flag to `true` will generate resolver signature that has only `resolveType` for interfaces, forcing developers to write inherited type resolvers in the type itself.
599- */
600- onlyResolveTypeForInterfaces ?: boolean ;
601596 /**
602597 * @description Makes `__typename` of resolver mappings non-optional without affecting the base types.
603598 * @default false
@@ -700,7 +695,8 @@ export class BaseResolversVisitor<
700695 rawConfig : TRawConfig ,
701696 additionalConfig : TPluginConfig ,
702697 private _schema : GraphQLSchema ,
703- defaultScalars : NormalizedScalarsMap = DEFAULT_SCALARS
698+ defaultScalars : NormalizedScalarsMap = DEFAULT_SCALARS ,
699+ federationMeta : FederationMeta = { }
704700 ) {
705701 super ( rawConfig , {
706702 immutableTypes : getConfigValue ( rawConfig . immutableTypes , false ) ,
@@ -714,7 +710,6 @@ export class BaseResolversVisitor<
714710 mapOrStr : rawConfig . enumValues ,
715711 } ) ,
716712 addUnderscoreToArgsType : getConfigValue ( rawConfig . addUnderscoreToArgsType , false ) ,
717- onlyResolveTypeForInterfaces : getConfigValue ( rawConfig . onlyResolveTypeForInterfaces , false ) ,
718713 contextType : parseMapper ( rawConfig . contextType || 'any' , 'ContextType' ) ,
719714 fieldContextTypes : getConfigValue ( rawConfig . fieldContextTypes , [ ] ) ,
720715 directiveContextTypes : getConfigValue ( rawConfig . directiveContextTypes , [ ] ) ,
@@ -729,9 +724,7 @@ export class BaseResolversVisitor<
729724 mappers : transformMappers ( rawConfig . mappers || { } , rawConfig . mapperTypeSuffix ) ,
730725 scalars : buildScalarsFromConfig ( _schema , rawConfig , defaultScalars ) ,
731726 internalResolversPrefix : getConfigValue ( rawConfig . internalResolversPrefix , '__' ) ,
732- generateInternalResolversIfNeeded : {
733- __resolveReference : rawConfig . generateInternalResolversIfNeeded ?. __resolveReference ?? false ,
734- } ,
727+ generateInternalResolversIfNeeded : { } ,
735728 resolversNonOptionalTypename : normalizeResolversNonOptionalTypename (
736729 getConfigValue ( rawConfig . resolversNonOptionalTypename , false )
737730 ) ,
@@ -740,7 +733,11 @@ export class BaseResolversVisitor<
740733 } as TPluginConfig ) ;
741734
742735 autoBind ( this ) ;
743- this . _federation = new ApolloFederation ( { enabled : this . config . federation , schema : this . schema } ) ;
736+ this . _federation = new ApolloFederation ( {
737+ enabled : this . config . federation ,
738+ schema : this . schema ,
739+ meta : federationMeta ,
740+ } ) ;
744741 this . _rootTypeNames = getRootTypeNames ( _schema ) ;
745742 this . _variablesTransformer = new OperationVariablesToObject (
746743 this . scalars ,
@@ -1358,7 +1355,9 @@ export class BaseResolversVisitor<
13581355
13591356 const federationMeta = this . _federation . getMeta ( ) [ schemaTypeName ] ;
13601357 if ( federationMeta ) {
1361- userDefinedTypes [ schemaTypeName ] . federation = federationMeta ;
1358+ userDefinedTypes [ schemaTypeName ] . federation = {
1359+ hasResolveReference : federationMeta . hasResolveReference ,
1360+ } ;
13621361 }
13631362 }
13641363
@@ -1474,9 +1473,10 @@ export class BaseResolversVisitor<
14741473 const baseType = getBaseTypeNode ( original . type ) ;
14751474 const realType = baseType . name . value ;
14761475 const parentType = this . schema . getType ( parentName ) ;
1476+ const meta : ReturnType < FieldDefinitionPrintFn > [ 'meta' ] = { } ;
14771477
14781478 if ( this . _federation . skipField ( { fieldNode : original , parentType } ) ) {
1479- return null ;
1479+ return { value : null , meta } ;
14801480 }
14811481
14821482 const contextType = this . getContextType ( parentName , node ) ;
@@ -1516,7 +1516,7 @@ export class BaseResolversVisitor<
15161516 }
15171517 }
15181518
1519- const parentTypeSignature = this . _federation . transformParentType ( {
1519+ const parentTypeSignature = this . _federation . transformFieldParentType ( {
15201520 fieldNode : original ,
15211521 parentType,
15221522 parentTypeSignature : this . getParentTypeForSignature ( node ) ,
@@ -1545,29 +1545,22 @@ export class BaseResolversVisitor<
15451545 } ;
15461546
15471547 if ( this . _federation . isResolveReferenceField ( node ) ) {
1548- if ( this . config . generateInternalResolversIfNeeded . __resolveReference ) {
1549- const federationDetails = checkObjectTypeFederationDetails (
1550- parentType . astNode as ObjectTypeDefinitionNode ,
1551- this . _schema
1552- ) ;
1553-
1554- if ( ! federationDetails || federationDetails . resolvableKeyDirectives . length === 0 ) {
1555- return '' ;
1556- }
1548+ if ( ! this . _federation . getMeta ( ) [ parentType . name ] . hasResolveReference ) {
1549+ return { value : '' , meta } ;
15571550 }
1558-
1559- this . _federation . setMeta ( parentType . name , { hasResolveReference : true } ) ;
15601551 signature . type = 'ReferenceResolver' ;
1561- if ( signature . genericTypes . length >= 3 ) {
1562- signature . genericTypes = signature . genericTypes . slice ( 0 , 3 ) ;
1563- }
1552+ signature . genericTypes = [ mappedTypeKey , parentTypeSignature , contextType ] ;
1553+ meta . federation = { isResolveReference : true } ;
15641554 }
15651555
1566- return indent (
1567- `${ signature . name } ${ signature . modifier } : ${ signature . type } <${ signature . genericTypes . join (
1568- ', '
1569- ) } >${ this . getPunctuation ( declarationKind ) } `
1570- ) ;
1556+ return {
1557+ value : indent (
1558+ `${ signature . name } ${ signature . modifier } : ${ signature . type } <${ signature . genericTypes . join (
1559+ ', '
1560+ ) } >${ this . getPunctuation ( declarationKind ) } `
1561+ ) ,
1562+ meta,
1563+ } ;
15711564 } ;
15721565 }
15731566
@@ -1628,7 +1621,7 @@ export class BaseResolversVisitor<
16281621 ( rootType === 'mutation' && this . config . avoidOptionals . mutation ) ||
16291622 ( rootType === 'subscription' && this . config . avoidOptionals . subscription ) ||
16301623 ( rootType === false && this . config . avoidOptionals . resolvers )
1631- ) ;
1624+ ) . value ;
16321625 } ) ;
16331626
16341627 if ( ! rootType ) {
@@ -1645,10 +1638,11 @@ export class BaseResolversVisitor<
16451638 `ContextType = ${ this . config . contextType . type } ` ,
16461639 this . transformParentGenericType ( parentType ) ,
16471640 ] ;
1648- if ( this . _federation . getMeta ( ) [ typeName ] ) {
1649- const typeRef = `${ this . convertName ( 'FederationTypes' ) } ['${ typeName } ']` ;
1650- genericTypes . push ( `FederationType extends ${ typeRef } = ${ typeRef } ` ) ;
1651- }
1641+ this . _federation . addFederationTypeGenericIfApplicable ( {
1642+ genericTypes,
1643+ federationTypesType : this . convertName ( 'FederationTypes' ) ,
1644+ typeName,
1645+ } ) ;
16521646
16531647 const block = new DeclarationBlock ( this . _declarationBlockConfig )
16541648 . export ( )
@@ -1837,25 +1831,44 @@ export class BaseResolversVisitor<
18371831 }
18381832
18391833 const parentType = this . getParentTypeToUse ( typeName ) ;
1834+
1835+ const genericTypes : string [ ] = [
1836+ `ContextType = ${ this . config . contextType . type } ` ,
1837+ this . transformParentGenericType ( parentType ) ,
1838+ ] ;
1839+ this . _federation . addFederationTypeGenericIfApplicable ( {
1840+ genericTypes,
1841+ federationTypesType : this . convertName ( 'FederationTypes' ) ,
1842+ typeName,
1843+ } ) ;
1844+
18401845 const possibleTypes = implementingTypes . map ( name => `'${ name } '` ) . join ( ' | ' ) || 'null' ;
1841- const fields = this . config . onlyResolveTypeForInterfaces ? [ ] : node . fields || [ ] ;
1846+
1847+ // An Interface has __resolveType resolver, and no other fields.
1848+ const blockFields : string [ ] = [
1849+ indent (
1850+ `${ this . config . internalResolversPrefix } resolveType${
1851+ this . config . optionalResolveType ? '?' : ''
1852+ } : TypeResolveFn<${ possibleTypes } , ParentType, ContextType>${ this . getPunctuation ( declarationKind ) } `
1853+ ) ,
1854+ ] ;
1855+
1856+ // An Interface in Federation may have the additional __resolveReference resolver, if resolvable.
1857+ // So, we filter out the normal fields declared on the Interface and add the __resolveReference resolver.
1858+ const fields = ( node . fields as unknown as FieldDefinitionPrintFn [ ] ) . map ( f =>
1859+ f ( typeName , this . config . avoidOptionals . resolvers )
1860+ ) ;
1861+ for ( const field of fields ) {
1862+ if ( field . meta . federation ?. isResolveReference ) {
1863+ blockFields . push ( field . value ) ;
1864+ }
1865+ }
18421866
18431867 return new DeclarationBlock ( this . _declarationBlockConfig )
18441868 . export ( )
18451869 . asKind ( declarationKind )
1846- . withName ( name , `<ContextType = ${ this . config . contextType . type } , ${ this . transformParentGenericType ( parentType ) } >` )
1847- . withBlock (
1848- [
1849- indent (
1850- `${ this . config . internalResolversPrefix } resolveType${
1851- this . config . optionalResolveType ? '?' : ''
1852- } : TypeResolveFn<${ possibleTypes } , ParentType, ContextType>${ this . getPunctuation ( declarationKind ) } `
1853- ) ,
1854- ...( fields as unknown as FieldDefinitionPrintFn [ ] ) . map ( f =>
1855- f ( typeName , this . config . avoidOptionals . resolvers )
1856- ) ,
1857- ] . join ( '\n' )
1858- ) . string ;
1870+ . withName ( name , `<${ genericTypes . join ( ', ' ) } >` )
1871+ . withBlock ( blockFields . join ( '\n' ) ) . string ;
18591872 }
18601873
18611874 SchemaDefinition ( ) {
0 commit comments