Skip to content

Commit

Permalink
Fix issue here source directive was not getting mapped to the correct…
Browse files Browse the repository at this point in the history
… types after multiple transformations were applied
  • Loading branch information
uzair-inamdar committed Oct 17, 2024
1 parent 93aa824 commit a5487f5
Showing 1 changed file with 41 additions and 4 deletions.
45 changes: 41 additions & 4 deletions packages/fusion/composition/src/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import type {
GraphQLArgumentConfig,
GraphQLFieldConfig,
GraphQLFieldConfigArgumentMap,
GraphQLList,
GraphQLNamedType,
GraphQLOutputType,
} from 'graphql';
import {
concatAST,
Expand All @@ -24,6 +26,7 @@ import {
MapperKind,
mapSchema,
type Constructor,
type DirectableObject,
type FieldMapper,
} from '@graphql-tools/utils';
import type { ServiceDefinition } from '@theguild/federation-composition';
Expand Down Expand Up @@ -332,12 +335,46 @@ export function getAnnotatedSubgraphs(
const fieldMapper: FieldMapper = (fieldConfig, fieldName) => {
const fieldDirectives = getDirectiveExtensions(fieldConfig);
const sourceDirectives = fieldDirectives?.source;
const typeNameSourceDirectives = getDirectiveExtensions(
((fieldConfig.type as GraphQLList<GraphQLOutputType>).ofType ||
fieldConfig.type) as DirectableObject,
)?.source;
// Find the @source directive that has the type's name by ignoring the one that might be present for type translation.
const typeNameSourceDirectiveName = typeNameSourceDirectives?.find(
sourceDirective => !sourceDirective.type,
)?.name;

if (sourceDirectives?.length) {
const filteredSourceDirectives = sourceDirectives.filter(
sourceDirective =>
const filteredSourceDirectives = sourceDirectives.filter(sourceDirective => {
// @source directive is redundant if fieldName and source type are same as in the field definition.
return (
sourceDirective.name !== fieldName ||
sourceDirective.type !== fieldConfig.type.toString(),
);
// If the field name is same as the @source directive name, we need to make sure the type value is mapped to the existing
// schema defined name or should map to the type's @source directive name.
(sourceDirective.type !== fieldConfig.type.toString() &&
sourceDirective.type === typeNameSourceDirectiveName)
);
});

// For each type @source directive, make sure the type is mapped to the correct schema type.
// If not, set it to a reasonable value.
for (const filteredSourceDirective of filteredSourceDirectives) {
if (!filteredSourceDirective.type) {
continue;
}
const isTypeMapped =
filteredSourceDirective.type === fieldConfig.type?.toString() ||
// The type's @source directive name will not have list or non-null representation.
filteredSourceDirective.type.search(
new RegExp(`^\\[?${typeNameSourceDirectiveName}!?\\]?!?$`),
) > -1;

if (!isTypeMapped) {
filteredSourceDirective.type = fieldConfig.type
?.toString()
.replace(/^(\[)?(.*)(!?\]!?|!)$/, `$1${typeNameSourceDirectiveName || '$2'}$3`);
}
}
fieldDirectives.source = filteredSourceDirectives;
}
if ('args' in fieldConfig) {
Expand Down

0 comments on commit a5487f5

Please sign in to comment.