@theguild/federation-composition
Version:
Open Source Composition library for Apollo Federation
42 lines (41 loc) • 2.1 kB
JavaScript
import { GraphQLError } from 'graphql';
import { andList } from '../../../utils/format.js';
export function InvalidFieldSharingRule(context) {
return {
ObjectTypeField(objectTypeState, fieldState) {
if (fieldState.usedAsKey &&
Array.from(fieldState.byGraph.values()).every(field => field.usedAsKey)) {
return;
}
const nonSharableIn = [];
const resolvableIn = [];
for (const [graphId, field] of fieldState.byGraph) {
const objectTypeIsShareable = objectTypeState.byGraph.get(graphId).shareable;
const fieldIsShareable = field.shareable;
const fieldIsExternal = field.external;
const fieldHasOverride = field.override;
const fieldIsUsedAsKey = field.usedAsKey;
if (fieldIsExternal || fieldHasOverride) {
continue;
}
if (objectTypeIsShareable || fieldIsShareable || fieldIsUsedAsKey) {
resolvableIn.push(graphId);
continue;
}
nonSharableIn.push(graphId);
resolvableIn.push(graphId);
}
if (nonSharableIn.length >= 1 && resolvableIn.length > 1) {
const isNonSharableInAll = resolvableIn.every(graphId => nonSharableIn.includes(graphId));
const message = `Non-shareable field "${objectTypeState.name}.${fieldState.name}" is resolved from multiple subgraphs: it is resolved from subgraphs ${andList(resolvableIn.map(context.graphIdToName), false, '"')} and defined as non-shareable in ${isNonSharableInAll
? 'all of them'
: `subgraph${nonSharableIn.length > 1 ? 's' : ''} ${andList(nonSharableIn.map(context.graphIdToName), true, '"')}`}`;
context.reportError(new GraphQLError(message, {
extensions: {
code: 'INVALID_FIELD_SHARING',
},
}));
}
},
};
}