UNPKG

@graphql-tools/stitch

Version:

A set of utils for faster development of GraphQL tools

79 lines (78 loc) 3.33 kB
import { Kind, } from 'graphql'; import { extractUnavailableFields } from '@graphql-tools/delegate'; import { collectSubFields } from '@graphql-tools/utils'; export function getFieldsNotInSubschema(schema, stitchingInfo, gatewayType, subschemaType, fieldNodes, fragments, variableValues) { const { fields: subFieldNodesByResponseKey } = collectSubFields(schema, fragments, variableValues, gatewayType, fieldNodes); // TODO: Verify whether it is safe that extensions always exists. const fieldNodesByField = stitchingInfo?.fieldNodesByField; const shouldAdd = (fieldType, selection) => !fieldNodesByField?.[fieldType.name]?.[selection.name.value]; const fields = subschemaType.getFields(); const fieldsNotInSchema = new Set(); for (const [, subFieldNodes] of subFieldNodesByResponseKey) { const fieldName = subFieldNodes[0].name.value; if (!fields[fieldName]) { for (const subFieldNode of subFieldNodes) { fieldsNotInSchema.add(subFieldNode); } } else { const field = fields[fieldName]; for (const subFieldNode of subFieldNodes) { const unavailableFields = extractUnavailableFields(schema, field, subFieldNode, shouldAdd); if (unavailableFields.length) { fieldsNotInSchema.add({ ...subFieldNode, selectionSet: { kind: Kind.SELECTION_SET, selections: unavailableFields, }, }); } } } let addedSubFieldNodes = false; const fieldNodesByFieldForType = fieldNodesByField?.[gatewayType.name]; const visitedFieldNames = new Set(); if (fieldNodesByFieldForType) { addMissingRequiredFields({ fieldName, fields, fieldsNotInSchema, visitedFieldNames, onAdd: () => { if (!addedSubFieldNodes) { for (const subFieldNode of subFieldNodes) { fieldsNotInSchema.add(subFieldNode); } addedSubFieldNodes = true; } }, fieldNodesByField: fieldNodesByFieldForType, }); } } return Array.from(fieldsNotInSchema); } function addMissingRequiredFields({ fieldName, fields, fieldsNotInSchema, onAdd, fieldNodesByField, visitedFieldNames, }) { if (visitedFieldNames.has(fieldName)) { return; } visitedFieldNames.add(fieldName); const fieldNodesForField = fieldNodesByField?.[fieldName]; if (fieldNodesForField) { for (const fieldNode of fieldNodesForField) { if (fieldNode.name.value !== '__typename' && !fields[fieldNode.name.value]) { onAdd(); fieldsNotInSchema.add(fieldNode); addMissingRequiredFields({ fieldName: fieldNode.name.value, fields, fieldsNotInSchema, onAdd, fieldNodesByField, visitedFieldNames, }); } } } }