UNPKG

gqlcheck

Version:

Performs additional checks on your GraphQL documents and operations to ensure they conform to your rules, whilst allow-listing existing operations and their constituent parts (and allowing overrides on a per-field basis). Rules include max selection set d

180 lines (179 loc) 5.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateBaseline = generateBaseline; exports.sortBaseline = sortBaseline; exports.filterBaseline = filterBaseline; exports.filterOnlyErrors = filterOnlyErrors; function generateBaseline(resultsBySourceName) { const baseline = { version: 1, operations: {}, }; for (const [_sourceName, { output }] of Object.entries(resultsBySourceName)) { const { errors } = output; for (const error of errors) { if ("infraction" in error) { // Rule error const { operations, infraction } = error; if (!operations) continue; for (const { operationName, operationCoordinates } of operations) { if (!operationName) continue; if (!baseline.operations[operationName]) { baseline.operations[operationName] = { ignoreCoordinatesByRule: Object.create(null), }; } const op = baseline.operations[operationName]; if (!op.ignoreCoordinatesByRule[infraction]) { op.ignoreCoordinatesByRule[infraction] = []; } const ignores = op.ignoreCoordinatesByRule[infraction]; for (const coord of operationCoordinates) { if (!ignores.includes(coord)) { ignores.push(coord); } } } } } } return sortBaseline(baseline); } function sortIgnoreCoordinatesByRule(icbr) { return Object.fromEntries(Object.entries(icbr) .sort((a, z) => { return a[0].localeCompare(z[0], "en-US"); }) .map(([key, arr]) => [key, arr != null ? [...arr].sort() : arr])); } function sortOperations(ops) { return Object.fromEntries(Object.entries(ops) .sort((a, z) => a[0].localeCompare(z[0], "en-US")) .map(([opName, val]) => { if (val != null) { const { ignoreCoordinatesByRule, ...rest } = val; return [ opName, { ignoreCoordinatesByRule: sortIgnoreCoordinatesByRule(ignoreCoordinatesByRule), ...rest, }, ]; } else { return [opName, val]; } })); } function sortBaseline(baseline) { const { version, operations, ...rest } = baseline; return { version, operations: sortOperations(operations), ...rest, }; } function filterOutput(baseline, output) { const { errors: rawErrors } = output; let filtered = 0; const errors = rawErrors .map((e) => { if ("infraction" in e) { const { infraction, operations: rawOperations } = e; if (!rawOperations) { return e; } const operations = rawOperations .map((op) => { const { operationName, operationCoordinates: rawCoords } = op; if (operationName == null) { return op; } const ignores = baseline.operations[operationName]?.ignoreCoordinatesByRule[infraction] ?? []; if (ignores.length === 0) { return op; } const operationCoordinates = rawCoords.filter((c) => !ignores.includes(c)); if (operationCoordinates.length === 0) { // Fully ignored return null; } op.operationCoordinates = operationCoordinates; return op; }) .filter((o) => o != null); if (operations.length === 0) { filtered++; return null; } else { e.operations = operations; return e; } } else { return e; } }) .filter((e) => e != null); return { ...output, errors, filtered, }; } function filterOutputOnlyErrors(output) { const { errors: rawErrors } = output; let filtered = 0; const errors = rawErrors .map((e) => { if ("infraction" in e) { filtered++; return null; } else { return e; } }) .filter((e) => e != null); return { ...output, errors, filtered, }; } function filterBaseline(baseline, result) { let filtered = 0; const entries = Object.entries(result.rawResultsBySourceName) .map(([sourceName, { output: rawOutput }]) => { const output = filterOutput(baseline, rawOutput); filtered += output.filtered; return [sourceName, { output }]; }) .filter((e) => e != null); const resultsBySourceName = Object.fromEntries(entries); return { ...result, baseline, resultsBySourceName, filtered, }; } function filterOnlyErrors(result) { let filtered = 0; const entries = Object.entries(result.rawResultsBySourceName) .map(([sourceName, { output: rawOutput }]) => { const output = filterOutputOnlyErrors(rawOutput); filtered += output.filtered; return [sourceName, { output }]; }) .filter((e) => e != null); const resultsBySourceName = Object.fromEntries(entries); return { ...result, resultsBySourceName, filtered, }; }