UNPKG

@graphql-tools/stitch

Version:

A set of utils for faster development of GraphQL tools

131 lines (130 loc) 6.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractUnavailableFields = exports.extractUnavailableFieldsFromSelectionSet = exports.getFieldsNotInSubschema = void 0; const graphql_1 = require("graphql"); const utils_1 = require("@graphql-tools/utils"); function getFieldsNotInSubschema(schema, stitchingInfo, gatewayType, subschemaType, fieldNodes, fragments, variableValues) { const { fields: subFieldNodesByResponseKey } = (0, utils_1.collectSubFields)(schema, fragments, variableValues, gatewayType, fieldNodes); // TODO: Verify whether it is safe that extensions always exists. const fieldNodesByField = stitchingInfo?.fieldNodesByField; 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, (fieldType, selection) => !fieldNodesByField?.[fieldType.name]?.[selection.name.value]); if (unavailableFields.length) { fieldsNotInSchema.add({ ...subFieldNode, selectionSet: { kind: graphql_1.Kind.SELECTION_SET, selections: unavailableFields, }, }); } } } const fieldNodesForField = fieldNodesByField?.[gatewayType.name]?.[fieldName]; if (fieldNodesForField) { for (const fieldNode of fieldNodesForField) { if (fieldNode.name.value !== '__typename' && !fields[fieldNode.name.value]) { // consider node that depends on something not in the schema as not in the schema for (const subFieldNode of subFieldNodes) { fieldsNotInSchema.add(subFieldNode); } fieldsNotInSchema.add(fieldNode); } } } } return Array.from(fieldsNotInSchema); } exports.getFieldsNotInSubschema = getFieldsNotInSubschema; function extractUnavailableFieldsFromSelectionSet(schema, fieldType, fieldSelectionSet, shouldAdd) { if ((0, graphql_1.isLeafType)(fieldType)) { return []; } if ((0, graphql_1.isUnionType)(fieldType)) { const unavailableSelections = []; for (const type of fieldType.getTypes()) { // Exclude other inline fragments const fieldSelectionExcluded = { ...fieldSelectionSet, selections: fieldSelectionSet.selections.filter(selection => selection.kind === graphql_1.Kind.INLINE_FRAGMENT ? selection.typeCondition ? selection.typeCondition.name.value === type.name : false : true), }; unavailableSelections.push(...extractUnavailableFieldsFromSelectionSet(schema, type, fieldSelectionExcluded, shouldAdd)); } return unavailableSelections; } const subFields = fieldType.getFields(); const unavailableSelections = []; for (const selection of fieldSelectionSet.selections) { if (selection.kind === graphql_1.Kind.FIELD) { if (selection.name.value === '__typename') { continue; } const fieldName = selection.name.value; const selectionField = subFields[fieldName]; if (!selectionField) { if (shouldAdd(fieldType, selection)) { unavailableSelections.push(selection); } } else { const unavailableSubFields = extractUnavailableFields(schema, selectionField, selection, shouldAdd); if (unavailableSubFields.length) { unavailableSelections.push({ ...selection, selectionSet: { kind: graphql_1.Kind.SELECTION_SET, selections: unavailableSubFields, }, }); } } } else if (selection.kind === graphql_1.Kind.INLINE_FRAGMENT) { const subFieldType = selection.typeCondition ? schema.getType(selection.typeCondition.name.value) : fieldType; if (!((0, graphql_1.isInterfaceType)(subFieldType) && (0, graphql_1.isObjectType)(subFieldType)) || subFieldType === fieldType || ((0, graphql_1.isInterfaceType)(fieldType) && schema.isSubType(fieldType, subFieldType))) { const unavailableFields = extractUnavailableFieldsFromSelectionSet(schema, fieldType, selection.selectionSet, shouldAdd); if (unavailableFields.length) { unavailableSelections.push({ ...selection, selectionSet: { kind: graphql_1.Kind.SELECTION_SET, selections: unavailableFields, }, }); } } else { unavailableSelections.push(selection); } } } return unavailableSelections; } exports.extractUnavailableFieldsFromSelectionSet = extractUnavailableFieldsFromSelectionSet; function extractUnavailableFields(schema, field, fieldNode, shouldAdd) { if (fieldNode.selectionSet) { const fieldType = (0, graphql_1.getNamedType)(field.type); return extractUnavailableFieldsFromSelectionSet(schema, fieldType, fieldNode.selectionSet, shouldAdd); } return []; } exports.extractUnavailableFields = extractUnavailableFields;