@apollo/query-planner
Version:
Apollo Query Planner
64 lines • 2.68 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateRecursiveSelections = void 0;
const federation_internals_1 = require("@apollo/federation-internals");
const MAX_RECURSIVE_SELECTIONS = 10000000;
function countRecursiveSelections(operation, fragmentCache, selectionSet, count) {
for (const selection of selectionSet.selections()) {
count++;
if (count > MAX_RECURSIVE_SELECTIONS) {
return null;
}
switch (selection.kind) {
case 'FieldSelection': {
if (selection.selectionSet) {
const result = countRecursiveSelections(operation, fragmentCache, selection.selectionSet, count);
if (result === null)
return null;
count = result;
}
break;
}
case 'FragmentSelection': {
if (selection instanceof federation_internals_1.FragmentSpreadSelection) {
const name = selection.namedFragment.name;
const cached = fragmentCache.get(name);
if (cached !== undefined) {
count = count + cached;
if (count > MAX_RECURSIVE_SELECTIONS) {
return null;
}
}
else {
const oldCount = count;
const result = countRecursiveSelections(operation, fragmentCache, selection.selectionSet, count);
if (result === null)
return null;
count = result;
fragmentCache.set(name, count - oldCount);
}
}
else {
const result = countRecursiveSelections(operation, fragmentCache, selection.selectionSet, count);
if (result === null)
return null;
count = result;
}
break;
}
default:
(0, federation_internals_1.assertUnreachable)(selection);
}
}
return count;
}
function validateRecursiveSelections(operation) {
const fragmentCache = new Map();
const result = countRecursiveSelections(operation, fragmentCache, operation.selectionSet, 0);
if (result === null) {
throw new Error('Exceeded maximum recursive selections in this operation');
}
}
exports.validateRecursiveSelections = validateRecursiveSelections;
;
//# sourceMappingURL=recursiveSelectionsLimit.js.map
;