@graphql-tools/stitch
Version:
A set of utils for faster development of GraphQL tools
131 lines (130 loc) • 6.17 kB
JavaScript
"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;