Spaces:
Running
Running
import { inspect } from '../../jsutils/inspect.mjs'; | |
import { GraphQLError } from '../../error/GraphQLError.mjs'; | |
import { isCompositeType } from '../../type/definition.mjs'; | |
import { doTypesOverlap } from '../../utilities/typeComparators.mjs'; | |
import { typeFromAST } from '../../utilities/typeFromAST.mjs'; | |
/** | |
* Possible fragment spread | |
* | |
* A fragment spread is only valid if the type condition could ever possibly | |
* be true: if there is a non-empty intersection of the possible parent types, | |
* and possible types which pass the type condition. | |
*/ | |
export function PossibleFragmentSpreadsRule(context) { | |
return { | |
InlineFragment(node) { | |
const fragType = context.getType(); | |
const parentType = context.getParentType(); | |
if ( | |
isCompositeType(fragType) && | |
isCompositeType(parentType) && | |
!doTypesOverlap(context.getSchema(), fragType, parentType) | |
) { | |
const parentTypeStr = inspect(parentType); | |
const fragTypeStr = inspect(fragType); | |
context.reportError( | |
new GraphQLError( | |
`Fragment cannot be spread here as objects of type "${parentTypeStr}" can never be of type "${fragTypeStr}".`, | |
{ | |
nodes: node, | |
}, | |
), | |
); | |
} | |
}, | |
FragmentSpread(node) { | |
const fragName = node.name.value; | |
const fragType = getFragmentType(context, fragName); | |
const parentType = context.getParentType(); | |
if ( | |
fragType && | |
parentType && | |
!doTypesOverlap(context.getSchema(), fragType, parentType) | |
) { | |
const parentTypeStr = inspect(parentType); | |
const fragTypeStr = inspect(fragType); | |
context.reportError( | |
new GraphQLError( | |
`Fragment "${fragName}" cannot be spread here as objects of type "${parentTypeStr}" can never be of type "${fragTypeStr}".`, | |
{ | |
nodes: node, | |
}, | |
), | |
); | |
} | |
}, | |
}; | |
} | |
function getFragmentType(context, name) { | |
const frag = context.getFragment(name); | |
if (frag) { | |
const type = typeFromAST(context.getSchema(), frag.typeCondition); | |
if (isCompositeType(type)) { | |
return type; | |
} | |
} | |
} | |