@theguild/federation-composition
Version:
Open Source Composition library for Apollo Federation
90 lines (89 loc) • 4.33 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FieldsOfTheSameTypeRule = void 0;
const graphql_1 = require("graphql");
function FieldsOfTheSameTypeRule(context) {
return {
ObjectTypeField(objectTypeState, fieldState) {
const typeToGraphs = new Map();
fieldState.byGraph.forEach((field, graphName) => {
const isNullable = !field.type.endsWith('!');
const isNullableInSupergraph = !fieldState.type.endsWith('!');
const isMatchingNonNullablePart = fieldState.type.replace(/!$/, '') === field.type.replace(/!$/, '');
let normalizedOutputType;
if (isMatchingNonNullablePart) {
normalizedOutputType = isNullableInSupergraph
? isNullable
? field.type
: field.type.replace(/!$/, '')
: field.type;
}
else {
normalizedOutputType = field.type;
}
const existing = typeToGraphs.get(normalizedOutputType);
if (existing) {
existing.push(graphName);
}
else {
typeToGraphs.set(normalizedOutputType, [graphName]);
}
});
if (typeToGraphs.size > 1) {
const groups = Array.from(typeToGraphs.entries()).map(([outputType, graphs]) => {
const plural = graphs.length > 1 ? 's' : '';
return `type "${outputType}" in subgraph${plural} "${graphs
.map(context.graphIdToName)
.join('", "')}"`;
});
const [first, second, ...rest] = groups;
context.reportError(new graphql_1.GraphQLError(`Type of field "${objectTypeState.name}.${fieldState.name}" is incompatible across subgraphs: it has ${first} but ${second}${rest.length ? ` and ${rest.join(' and ')}` : ''}`, {
extensions: {
code: 'FIELD_TYPE_MISMATCH',
},
}));
}
},
InputObjectTypeField(inputObjectTypeState, fieldState) {
const typeToGraphs = new Map();
fieldState.byGraph.forEach((field, graphName) => {
const isNonNullable = field.type.endsWith('!');
const isNonNullableInSupergraph = fieldState.type.endsWith('!');
const isMatchingNonNullablePart = fieldState.type.replace(/!$/, '') === field.type.replace(/!$/, '');
let normalizedOutputType;
if (isMatchingNonNullablePart) {
normalizedOutputType = isNonNullableInSupergraph
? isNonNullable
? field.type
: field.type + '!'
: field.type;
}
else {
normalizedOutputType = field.type;
}
const existing = typeToGraphs.get(normalizedOutputType);
if (existing) {
existing.push(graphName);
}
else {
typeToGraphs.set(normalizedOutputType, [graphName]);
}
});
if (typeToGraphs.size > 1) {
const groups = Array.from(typeToGraphs.entries()).map(([outputType, graphs]) => {
const plural = graphs.length > 1 ? 's' : '';
return `type "${outputType}" in subgraph${plural} "${graphs
.map(context.graphIdToName)
.join('", "')}"`;
});
const [first, second, ...rest] = groups;
context.reportError(new graphql_1.GraphQLError(`Type of field "${inputObjectTypeState.name}.${fieldState.name}" is incompatible across subgraphs: it has ${first} but ${second}${rest.length ? ` and ${rest.join(' and ')}` : ''}`, {
extensions: {
code: 'FIELD_TYPE_MISMATCH',
},
}));
}
},
};
}
exports.FieldsOfTheSameTypeRule = FieldsOfTheSameTypeRule;