UNPKG

@apollo/query-planner

Version:
64 lines 2.68 kB
"use strict"; 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