@graphql-tools/delegate
Version:
A set of utils for faster development of GraphQL tools
101 lines (100 loc) • 5.52 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.OverlappingAliasesTransform = void 0;
const graphql_1 = require("graphql");
const OverlappingAliases = Symbol('OverlappingAliases');
class OverlappingAliasesTransform {
transformRequest(request, delegationContext, transformationContext) {
const newDocument = (0, graphql_1.visit)(request.document, {
[graphql_1.Kind.SELECTION_SET]: node => {
const seenNonNullable = new Set();
const seenNullable = new Set();
return {
...node,
selections: node.selections.map(selection => {
if (selection.kind === graphql_1.Kind.INLINE_FRAGMENT) {
const selectionTypeName = selection.typeCondition?.name.value;
if (selectionTypeName) {
const selectionType = delegationContext.transformedSchema.getType(selectionTypeName);
if (selectionType && 'getFields' in selectionType) {
const selectionTypeFields = selectionType.getFields();
return {
...selection,
selectionSet: {
...selection.selectionSet,
selections: selection.selectionSet.selections.map(subSelection => {
if (subSelection.kind === graphql_1.Kind.FIELD) {
const fieldName = subSelection.name.value;
if (!subSelection.alias) {
const field = selectionTypeFields[fieldName];
if (field) {
let currentNullable;
if ((0, graphql_1.isNullableType)(field.type)) {
seenNullable.add(fieldName);
currentNullable = true;
}
else {
seenNonNullable.add(fieldName);
currentNullable = false;
}
if (seenNullable.has(fieldName) && seenNonNullable.has(fieldName)) {
transformationContext[OverlappingAliases] = true;
return {
...subSelection,
alias: {
kind: graphql_1.Kind.NAME,
value: currentNullable
? `_nullable_${fieldName}`
: `_nonNullable_${fieldName}`,
},
};
}
}
}
}
return subSelection;
}),
},
};
}
}
}
return selection;
}),
};
},
});
return {
...request,
document: newDocument,
};
}
transformResult(result, _delegationContext, transformationContext) {
if (transformationContext[OverlappingAliases]) {
return removeOverlappingAliases(result);
}
return result;
}
}
exports.OverlappingAliasesTransform = OverlappingAliasesTransform;
function removeOverlappingAliases(result) {
if (result != null) {
if (Array.isArray(result)) {
return result.map(removeOverlappingAliases);
}
else if (typeof result === 'object') {
const newResult = {};
for (const key in result) {
if (key.startsWith('_nullable_') || key.startsWith('_nonNullable_')) {
const newKey = key.replace(/^_nullable_/, '').replace(/^_nonNullable_/, '');
newResult[newKey] = removeOverlappingAliases(result[key]);
}
else {
newResult[key] = removeOverlappingAliases(result[key]);
}
}
return newResult;
}
}
return result;
}